2016-01-27 9 views
5

Di seguito è un programma che dimostra completamente il problema che sto vedendo.C++ 14 auto lambda può accettare Obj <std :: tuple <void>> - ma le funzioni modello non possono?

Per prima cosa, comincio con un oggetto che viene definito utilizzando un raggruppamento di altri tipi, ho iniziato a utilizzare una std :: tupla <> per gestire il raggruppamento.

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

Sono intendendo questi oggetti per essere in grado di avere il tipo void sparsi nel "pacchetto". Sono già a conoscenza di essere in grado di "istanziare" una tupla di questo tipo (vedi Void type in std::tuple)

voglio passare questi oggetti intorno, forse copiare/spostarli ... nessuno dei loro membri di dati sono un tupla di questi tipi. In effetti, posso riprodurre il problema utilizzando la definizione di oggetto vuoto sopra.

io posso farlo funzionare, utilizzando qualcosa di simile:

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

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

Questi tipi di "raggruppamento" le strutture sono utilizzate in frequenly ricorsione variadic, e hanno lo scopo di ottenere mai creato/usato. Solo per raggruppare gli argomenti del modello.

Tuttavia, "voglio" che la firma dell'oggetto sia composta da tipi/nomi "utente previsti".

Fondamentalmente, stavo sperimentando con ogni possibile modo di passare uno di questi oggetti intorno a quando std::tuple è usato per "gruppo", e potrebbe trovare solo in un modo: auto lambda.

Qualcuno può spiegare:

  1. perché del lambda "auto" può lavorare per questo?

    qualcosa sulla deduzione del modello ritardata? come il diff b/w "auto" e "decltype (auto)"?

  2. come "progettare" un parametro di funzione per accettare uno di questi oggetti.

- grazie a tutti voi per eventuali approfondimenti su questa stranezza

Esempio:

#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: l'aggiunta di un assettato giù riproduzione:

#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

[Codice più semplice da riprodurre] (http://goo.gl/i1xlK6) –

+0

@ M.M Sono nuovo a postare qui e ho pensato che stavi chiedendo un campione migliore ... quindi ho fatto clic sul collegamento. Bella pagina interattiva E sì, quell'esempio più breve è quello che sto vedendo. – CrashNeb

+0

Inoltre: sto utilizzando Visual Studio 2015, quindi utilizzando la pagina di M.M sono riuscito a vedere i messaggi di errore "migliori" di Clang. ;) Tuttavia, perché i modelli di classe lambda (generati internamente) gestiscono questo e i modelli "creati dall'utente" non possono? – CrashNeb

risposta

5

std::tuple<void> è un cl associato ass di object<std::tuple<void>>, quindi in una chiamata non qualificata in cui viene eseguita la ricerca dipendente dall'argomento, viene creata un'istanza std::tuple<void> per cercare le funzioni friend che potrebbero essere state definite in linea. Questa istanza causa un errore.

La ricerca dipendente dall'argomento non viene eseguita se la cosa chiamata non nomina un modello funzione o funzione; quindi utilizzando un lambda funziona - takeobj_lambda è un oggetto.

Se si utilizza una chiamata qualificata (::takeobj(oval)) o tra parentesi takeobj ((takeobj)(oval)), il codice viene compilato. Entrambi disabilitano l'ADL.

+0

Oh uomo (non riesco a immaginare di capirlo) ... grazie mille !. Erano solo 3 settimane fa che avevo trovato questa risposta [Quando si fanno parentesi aggiuntive ...] (http://stackoverflow.com/a/24116818/5844631), l'abbiamo messo tra i segnalibri e provato a memorizzarlo. Ma ahimè, mi ero "spostato" e avrei speso una quantità sconosciuta di tempo mentre non stavo facendo la connessione che ADL era il problema qui. – CrashNeb

Problemi correlati