2013-05-15 16 views
10

Załóżmy, że mam krotkiRozpakowywanie std-a do wskaźników?

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

mogę to zrobić:

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

Ale jeśli niektóre z tych krotek są naprawdę drogie, aby skopiować, co naprawdę chciałbym to zrobić odniesienie lub wskaźnik do właściwych miejsc w mojej krotce. Mogę to zrobić:

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

Ale to wydaje się tak kiepski w porównaniu do tego, jak niesamowite jest składnia tie. Czy istnieje inny sposób uzyskania wskaźników/odwołań do składników krotki?

+0

See Boost.Fusion –

+3

Przenoszenie z krotki może być najlepszym pomysłem w niektórych przypadkach - 'std :: tie (a, b, c) = std :: move (myFavoriteTuple);' – zch

+0

Oh man, C++ 17 is great: 'auto && [a, b, c] = myFavoriteTuple;' done. – Barry

Odpowiedz

5

Biorąc infrastruktura zwykłe indeksy:

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...> { }; 

Można by utworzyć funkcję, która zwraca krotki wskaźników, każdy element jest wskaźnik do odpowiedniego elementu krotki wejściowej:

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)>()); 
} 

I tak możesz go użyć:

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); 

Oto live example.

+1

@ Barry: Tak, często faceci z szablonów są zajęci na czacie w salonie, więc jestem wolny, aby powoli wkraść się i odpowiedzieć;) –

+0

Zastanawiasz się, czy ta propozycja pozwoliłaby na lepsze? http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html – balki

+0

@balki: Tak, to spowoduje standaryzację maszyn indeksowych –

0

Co z poniższymi?

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; 

Następnie można użyć *a.ptr, aby uzyskać dostęp do obiektu. Możesz nawet zastąpić operator-> itp., Jeśli masz na to ochotę.

Główną wadą tej metody jest wiązanie elementów krotek jako const, ze względu na operator=(const T&). Możesz go usunąć za pomocą ptr = const_cast<T*>(x), ale myślę, że w niektórych przypadkach może to złamać poprawność const.

Powiązane problemy