2016-01-27 5 views
5

Unten ist ein Programm, das das Problem, das ich sehe, vollständig zeigt.C++ 14 Auto Lambda kann Obj akzeptieren <std :: tuple <void>> - aber Vorlagenfunktionen können nicht?

Zuerst habe ich mit einem Objekt starten, die eine Gruppierung von anderen Typen definiert wird, begann ich eine std :: tuple <> die Gruppierung zu verwalten.

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

Ich bin diese Objekte beabsichtigen void im „Rudel“ verstreut in der Lage sein, die Art zu haben. Ich bin bereits bekannt, nicht in der Lage zu „instanziiert“ ein Tupel dieses Typs (siehe Void type in std::tuple)

Ich möchte um diese Objekte passieren, vielleicht kopieren/verschieben sie ... keine ihrer Datenelemente sind ein Tupel dieser Art. In der Tat kann ich das Problem mit der obigen leeren Objektdefinition reproduzieren.

ich kann es funktioniert, wie etwas mit:

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

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

Diese Arten von „Gruppierung“ structs werden frequenly in variadische Rekursion verwendet, und sie sollen nie erstellt/gewöhnen. Nur um Vorlagenargumente zu gruppieren.

Aber ich „will“ die Unterschrift des ‚Objekts‘ aus „user erwartet“ -Typen/Namen gemacht werden.

Im Grunde war ich das Experimentieren mit jede mögliche Art und Weise eines dieser Objekte, das um, wenn std::tuple zu „Gruppe“ verwendet wird, und nur einen Weg finden könnte: auto lambdas.

Kann jemand erklären:

  1. , warum die "auto" Lambda ist für diese Arbeit?

    etwas über verzögerte Vorlage Abzug? wie das diff b/w "auto" und "decltype (auto)"?

  2. wie „Design“ ein Funktionsparameter eines dieser Objekte zu akzeptieren.

- Dank an euch alle für irgendwelche Erkenntnisse über diese Kuriosität

Beispiel:

#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; 
} 

bearbeiten: Hinzufügen eine abgespeckte Wiedergabe:

#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

[Einfachere Code zu reproduzieren] (http://goo.gl/i1xlK6) –

+0

@ M. M ich hier zu veröffentlichen bin neu, und dachte, dass Sie für eine bessere Probe gefragt wurden ... dann klickte ich den Link. Coole interaktive Seite. Und, ja, dieses kürzere Beispiel ist das, was ich sehe. – CrashNeb

+0

Außerdem: Ich benutze Visual Studio 2015, also konnte ich die Seite von M.M die "besseren" Clang Fehlermeldungen sehen. ;) Immer noch, warum die Lambda (intern generierten) Klassenvorlagen dies verwalten und die "benutzerdefinierten" Vorlagen können nicht? – CrashNeb

Antwort

5

std::tuple<void> ist ein assoziierter cl ass von object<std::tuple<void>>, und so in einem uneingeschränkten Aufruf, in dem Argumente abhängige Suche durchgeführt wird, wird std::tuple<void> für alle friend Funktionen suchen instanziiert, die inline definiert worden sein könnten. Diese Instanziierung verursacht einen Fehler.

Argumentabhängige Suche wird nicht ausgeführt, wenn das aufgerufene Objekt keine Funktions- oder Funktionsvorlage angibt; Daher ist ein Lambda-Arbeiten - takeobj_lambda ein Objekt.

Wenn Sie entweder einen qualifizierten Anruf (::takeobj(oval)) oder in Klammern die Größe takeobj ((takeobj)(oval)) verwenden, wird der Code kompiliert. Beide deaktivieren ADL.

+0

Oh Mann (ich kann mir nicht vorstellen, das herauszufinden) ... vielen Dank! Es war nur 3 Wochen her, dass ich auf diese Antwort gestoßen war (http://stackoverflow.com/a/24116818/5844631), sie mit Lesezeichen versehen und versucht habe, mich daran zu erinnern. Aber ach, ich war "weitergezogen" und hätte eine unbekannte Menge an Zeit verbracht, ohne die Verbindung herzustellen, dass ADL das Problem hier war. – CrashNeb

Verwandte Themen