modello variadic ricorsivo per stampare il contenuto di un pacchetto di parametri

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.