2016-01-27 27 views
5

Poniżej znajduje się program, który całkowicie demonstruje problem, który widzę.C++ 14 auto lambda może zaakceptować Obj <std :: tuple <void>> - ale funkcje szablonu nie mogą?

Po pierwsze, zaczynam od obiektu zdefiniowanego za pomocą grupowania innych typów, zacząłem używać std :: tuple <> do zarządzania grupowaniem.

template <typename> class object; 
template <typename... Rs> class object<std::tuple<Rs...> > { 
}; 

Jestem zamierzając te obiekty się być zdolne do wywierania typ void rozproszone w „opakowaniu”. Jestem już świadomość bycia w stanie „instancji” krotki tego typu (patrz Void type in std::tuple)

Chcę przekazać te obiekty wokół, może skopiować/przenieść je ... żaden z ich członków danych się krotka tych typów. W rzeczywistości mogę odtworzyć problem za pomocą powyższej definicji pustego obiektu.

I może aby pracować, używając coś jak:

template <typename... Rs> struct TGrp {}; 

template <typename> class object; 
template <typename... Rs> class object<TGrp<Rs...> > { 
}; 

Tego typu „grupowania” struktury są wykorzystywane w zmiennej liczbie argumentów frequenly rekursji, a oni mają nigdy się stworzony/używane. Po prostu grupuj argumenty szablonu.

Jednak "chcę" podpis "obiektu" składa się z "typów/nazw oczekiwanych przez użytkownika".

Zasadniczo eksperymentował z ewentualne drogę przechodząc jedną z tych obiektów wokół kiedy std::tuple jest wykorzystywany do „grupy”, i może znaleźć tylko w jeden sposób: auto lambdy.

Czy ktoś może wyjaśnić:

  1. dlaczego "auto" lambda może pracować na to?

    coś o opóźnionym odliczeniu szablonów? jak diff b/w "auto" i "decltype (auto)"?

  2. jak "zaprojektować" parametr funkcji, aby zaakceptować jeden z tych obiektów.

- dzięki wam wszystkim za wszelkie spostrzeżenia na ten cudak

Przykład:

#include <tuple> 
#include <iostream> 

#define GRP std::tuple  // IF 'tuple' used: compile error where noted below 
//#define GRP TGrp   // if THIS is used: all works, and TGrp() is never constructed 


// Grouping mechanism 
template <typename... Ts> struct TGrp { 
    TGrp() { 
     std::cout << "Never printed message\n"; 
    } 
}; 


// MAIN OBJECT (empty for forum question) 
template <typename> class object; 
template <typename... Rs> class object<GRP<Rs...> > { 
}; 



// Regular function     (does NOT work) 
void takeobj(object<GRP<void> >& obj) { (void)obj; } 

// Lambda - taking anything...  (only thing I could make WORK) 
auto takeobj_lambda = [](auto obj) { (void)obj; }; 

// Template func - taking anything (does NOT work) 
template <typename T> void takeobj_templ_norm(T obj) { (void)obj; } 
template <typename T> void takeobj_templ_clref(const T& obj) { (void)obj; } 
template <typename T> void takeobj_templ_lref(T& obj) { (void)obj; } 
template <typename T> void takeobj_templ_rref(T&& obj) { (void)obj; } 


int main() 
{ 
    object<GRP<void> > oval; 

    //takeobj(oval);     // <-- causes compile error 

    takeobj_lambda(oval); // works 

    //takeobj_templ_norm(oval);  // <-- also error 
    //takeobj_templ_clref(oval);  // <-- also error 
    //takeobj_templ_lref(oval);  // <-- also error 
    //takeobj_templ_rref(oval);  // <-- also error 
    return 0; 
} 

Edit: dodanie okrojone reprodukcji:

#include <tuple> 


// MAIN OBJECT (empty for forum question) 
template <typename> class object; 
template <typename... Rs> class object<std::tuple<Rs...> > { 
}; 

// Regular function     (does NOT work) 
void takeobj(object<std::tuple<void> >& obj) { (void)obj; } 

// Lambda - taking anything...  (only thing I could make WORK) 
auto takeobj_lambda = [](auto obj) { (void)obj; }; 


int main() 
{ 
    object<std::tuple<void> > oval; 

    //takeobj(oval);     // <-- causes compile error 
    takeobj_lambda(oval); // works 

    return 0; 
} 
+3

[Prostszy kod do powielenia] (http://goo.gl/i1xlK6) –

+0

@ M.M Jestem nowy, aby opublikować tutaj i pomyślałem, że prosisz o lepszą próbkę ... następnie kliknąłem link. Fajna strona interaktywna. I tak, tym krótszym przykładem jest to, co widzę. – CrashNeb

+0

Ponadto: używam Visual Studio 2015, więc używając strony z M.M byłem w stanie zobaczyć "lepsze" komunikaty o błędach Clang. ;) Nadal jednak, dlaczego szablony klas lambda (generowane wewnętrznie) to zarządzają, a szablony "zbudowane przez użytkownika" nie mogą tego zrobić? – CrashNeb

Odpowiedz

5

std::tuple<void> jest połączonym kl. ass z object<std::tuple<void>>, a więc w niewykwalifikowanym wywołaniu, w którym wykonywane jest wyszukiwanie zależne od argumentów, tworzona jest instancja std::tuple<void> w celu wyszukania funkcji friend, które mogły zostać zdefiniowane jako wbudowane. Ta instancja powoduje błąd.

Wyszukiwanie zależne od argumentu nie jest wykonywane, jeśli wywoływana rzecz nie zawiera nazwy funkcji lub szablonu funkcji; stąd użycie obiektu lambda - obiekt jest obiektem takeobj_lambda.

Jeśli użyjesz kwalifikowanego połączenia (::takeobj(oval)) lub nawiążesz takeobj ((takeobj)(oval)), kod zostanie skompilowany. Oba wyłączają ADL.

+0

Och, człowieku (nie wyobrażam sobie tego wymyślić) ... dziękuję bardzo !. Dopiero 3 tygodnie temu natknąłem się na tę odpowiedź [Kiedy robię dodatkowe nawiasy ...] (http://stackoverflow.com/a/24116818/5844631), dodałem do zakładek i próbowałem ją zapamiętać. Ale niestety, "ruszyłem" i spędziłem nieznany czas, nie nawiązując połączenia, że ​​problemem jest tutaj ADL. – CrashNeb