2013-08-18 30 views
6

std::tuple zawiera, między innymi, następujące konstruktory:Czy konieczne są wszystkie konstruktory std :: tuple?

explicit tuple(const Types&... args); 

template< class... UTypes > 
explicit tuple(UTypes&&... args); 

Obie mają równoważne opisy w inicjalizacji że każdy z elementów z odpowiednią wartością w args. Jedyną różnicą jest to, że w drugim parametry są przekazywane.

Z tego, co zrozumiałem o referencjach rvalue, nie rozumiem, dlaczego pierwsza wersja jest wymagana, ponieważ te same parametry mogły zostać przekazane do drugiej wersji. Odniesienia zostaną przekazane i nikt nie będzie mądrzejszy, szczególnie, że nie ma wzmianki o semantyce ruchu.

Czy ktoś może wyjaśnić, co sprawia, że ​​oba konstruktory są potrzebne?

+3

Druga wersja jest SFINAE-d z przeciążeniem ustawiony jeśli nie wszystkich 'UTypes' są niejawnie zamienny do odpowiednich' Types' – jrok

Odpowiedz

10

Oto uproszczony przykład:

template <typename T> 
struct foo 
{ 
    foo(const T&); 
    template <typename U> 
    foo(U&&); 
}; 

Drugi konstruktor wymaga jakiegoś typu szablon odliczenia. To nie działa we wszystkich przypadkach, np. z listami inicjalizatora. Poniższy inicjalizacji działa tylko wtedy, gdy pierwszy konstruktor jest dostępny:

auto f = foo<std::vector<int>>{ { 1, 2, 3 } }; 
0

To dla spedycji odniesienia rvalue i jest zoptymalizowany do budowy ruchu. Pierwsza wersja jest używana dla wartości l. Zobacz poniższy link, aby lepiej wyjaśnić.

http://thbecker.net/articles/rvalue_references/section_07.html

+4

Druga wersja może być stosowany do odniesienia rvalue jak również odniesień lwartości. – nosid

+0

Uzgodnione, ale kompilator dokona najlepszego wyboru w czasie kompilacji dla podpisu funkcji iw tym przypadku mają 2 podpisy pod warunkiem. Zgadzam się z Twoją odpowiedzią, jak również pomaga to w odliczeniu szablonów i jest wymagane z tego powodu. – bjackfly