2013-05-15 4 views
10

Предположим, у меня есть кортежРаспаковка std tuple в указатели?

std::tuple<A, B, C> myFavoriteTuple; 

я могу это сделать:

A a; 
B b; 
C c; 
std::tie(a, b, c) = myFavoriteTuple 

Но если некоторые из этих кортежей действительно дорого, чтобы скопировать, что я бы очень хотел, чтобы получить ссылку или указатель на правильные пятна в моем кортеже. Я могу это сделать:

A* a = &std::get<0>(myFavoriteTuple); 
B* b = &std::get<1>(myFavoriteTuple); 
C* c = &std::get<2>(myFavoriteTuple); 

Но это кажется настолько хромает по сравнению с тем, как удивительный синтаксис tie есть. Есть ли другой способ получить указатели/ссылки на компоненты кортежа?

+0

Просмотреть Boost.Fusion –

+3

Перемещение из кортежа может быть лучшей идеей в некоторых случаях - 'std :: tie (a, b, c) = std :: move (myFavoriteTuple);' – zch

+0

О, человек, C++ 17 отлично: 'auto && [a, b, c] = myFavoriteTuple;' done. – Barry

ответ

5

Учитывая обычные показатели инфраструктуры:

template<int... Is> 
struct seq { }; 

template<int N, int... Is> 
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { }; 

template<int... Is> 
struct gen_seq<0, Is...> : seq<Is...> { }; 

Вы можете создать функцию, которая возвращает кортеж из указателей, каждый элемент представляет собой указатель на соответствующий элемент входного кортежа:

template<typename... Args, int... Is> 
auto make_pointer_tuple(std::tuple<Args...>& t, seq<Is...>) 
    -> std::tuple<typename std::add_pointer<Args>::type...> 
{ 
    return std::make_tuple(&std::get<Is>(t)...); 
} 

template<typename... Args> 
auto make_pointer_tuple(std::tuple<Args...>& t) 
    -> std::tuple<typename std::add_pointer<Args>::type...> 
{ 
    return make_pointer_tuple(t, gen_seq<sizeof...(Args)>()); 
} 

И вот как вы могли бы использовать его:

std::tuple<int, bool, std::string> myFavoriteTuple{0, false, ""}; 

int* pInt = nullptr; 
bool* pBool = nullptr; 
std::string* pString = nullptr; 
tie(pInt, pBool, pString) = make_pointer_tuple(myFavoriteTuple); 

live example.

+1

@ Барри: Да, часто парни шаблонов заняты разговором в лаундже, поэтому я свободен, чтобы медленно прокрасться и ответить;) –

+0

Хотите узнать, улучшится ли это предложение? http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html – balki

+0

@balki: Да, это будет стандартизировать систему индексов –

0

Как насчет следующего?

template<typename T> 
struct ptie 
{ 
    const T *ptr; 
    ptie() 
     :ptr(nullptr) 
    {} 

    void operator=(const T &x) 
    { 
     ptr = &x; 
    } 
}; 

ptie<A> a; 
ptie<B> b; 
ptie<C> c; 
std::tie(a, b, c) = myFavoriteTuple; 

Затем вы можете использовать *a.ptr для доступа к объекту. Вы даже можете переопределить operator-> и т. Д., Если вам это нравится.

Основным недостатком этого метода является то, что он связывает элементы кортежа как const, из-за operator=(const T&). Вы можете удалить его с помощью ptr = const_cast<T*>(x), но я думаю, что в некоторых случаях это может сломать const-correctness.

Смежные вопросы