Come è ansible creare un modello variadico ricorsivo per stampare il contenuto di un pacchetto di parametri? Sto provando con questo, ma non riesce a compilare:
template std::string type_name () { return std::string(typeid(First).name()) + " " + type_name(); } std::string type_name () { return ""; }
Come posso terminare la ricorsione?
È necessario utilizzare la specializzazione parziale per terminare la ricorsione, ma poiché non è ansible specializzare parzialmente le funzioni libere in C ++, è necessario creare una class di implementazione con una funzione membro statica.
template struct Impl; template struct Impl { static std::string name() { return std::string(typeid(First).name()) + " " + Impl::name(); } }; template <> struct Impl<> { static std::string name() { return ""; } }; template std::string type_name() { return Impl::name(); } int main() { std::cout << type_name() << std::endl; // "ibcd" return 0; }
Quella prima dichiarazione di Impl
è solo una soluzione per una lacuna in g ++ 4.6 (e sotto). Non sarà necessario una volta implementato correttamente i modelli variadici.
Guardalo in azione su ideone.com
C’è in realtà un modo molto elegante per terminare la ricorsione:
template std::string type_name () { return std::string(typeid(Last).name()); } template std::string type_name () { return std::string(typeid(First).name()) + " " + type_name(); }
Inizialmente ho provato template
e template
ma era considerato ambiguo (Rest può essere zero elementi). Questa domanda mi mostrò quindi la soluzione definitiva: Errore di compilazione sulla funzione modello variabile ricorsivo
Nota, per evitare un po ‘di duplicazione del codice, potresti anche fare:
template std::string type_name () { return std::string(typeid(Last).name()); } template std::string type_name () { return type_name() + " " + type_name(); }
In alternativa alla specializzazione parziale non esistente per le funzioni, è ansible utilizzare l’overloading su una class tipificatore:
#include #include #include template struct NumberToType { }; template std::string my_type_name(NumberToType<0> = NumberToType<0>()) { return std::string(typeid(T).name()); } template std::string my_type_name(NumberToType = NumberToType()) { return std::string(typeid(T).name()) + " " + my_type_name(NumberToType()); } int main() { std::cout << my_type_name() << std::endl; }
In alternativa, è ansible decomprimere il pacchetto di parametri sul posto come nell’esempio seguente:
#include #include #include template std::string type_name () { std::string str = typeid(T).name(); int arr[] = { 0, (str += std::string{" "} + typeid(Args).name(), 0)... }; (void)arr; return str; } int main() { auto str = type_name(); std::cout << str << std::endl; }
La ricorsione non è richiesta in realtà per farlo.