7

Kann ich variadische Vorlagen verwenden, ohne die Vorlagenparameter als Funktionsparameter zu verwenden?Variadic-Vorlagen ohne Funktionsparameter

Als ich sie verwenden, es kompiliert:

#include <iostream> 
using namespace std; 

template<class First> 
void print(First first) 
{ 
    cout << 1 << endl; 
} 

template<class First, class ... Rest> 
void print(First first, Rest ...rest) 
{ 
    cout << 1 << endl; 
    print<Rest...>(rest...); 
} 

int main() 
{ 
    print<int,int,int>(1,2,3); 
} 

Aber wenn ich sie nicht verwenden, es nicht kompilieren und beschwert sich über eine Zweideutigkeit:

#include <iostream> 
using namespace std; 

template<class First> 
void print() 
{ 
    cout << 1 << endl; 
} 

template<class First, class ... Rest> 
void print() 
{ 
    cout << 1 << endl; 
    print<Rest...>(); 
} 

int main() 
{ 
    print<int,int,int>(); 
} 

Leider sind die Klassen I wollen als Vorlage geben Parameter sind nicht instanziierbar (sie haben statische Funktionen, die innerhalb der Template-Funktion genannt werden). Gibt es eine Möglichkeit, dies zu tun?

+1

Wenn Sie eine * unevaluierten * Ausdruck eines bestimmten Typs benötigen, können Sie 'std :: declval ()'. Funktioniert für jedes "T", unabhängig davon, ob es konstruierbar ist oder nicht. –

+4

Warum funktioniert die No-Argument-Version nicht: Ohne Argumente sind die beiden Überladungen 'print ' und 'print ' gleich gut, während mit 'print (3)' eine bessere Übereinstimmung als 'print ist (3, {}) '(wobei' {} '" nichts "bedeutet). Keine Überladung, wie CatPusPus nahelegt, ist die Standardmethode; und da Sie Ihre Argumente sowieso nicht ableiten, ist das die einfachste Lösung. –

+0

Ich wollte eine Antwort posten, aber n.m. habe es schon gepostet. – bames53

Antwort

20
template<class First> // 1 template parameter 
void print() 
{ 
    cout << 1 << endl; 
} 

#if 0 
template<class First, class ... Rest> // >=1 template parameters -- ambiguity! 
void print() 
{ 
    cout << 1 << endl; 
    print<Rest...>(); 
} 
#endif 

template<class First, class Second, class ... Rest> // >=2 template parameters 
void print() 
{ 
    cout << 1 << endl; 
    print<Second, Rest...>(); 
} 
+1

Sie können die Code-Duplizierung loswerden, indem Sie 'print () 'von dieser untersten Version aufrufen, anstatt die' cout'-Zeile zu wiederholen. Ich denke. –

8

Machen Sie es zu einem Typ.

template <typename... Ts> 
struct print_impl; 

template <typename T> 
struct print_impl<T> { 
    static void run() { 
     std::cout << 1 << "\n"; 
    } 
}; 

template <typename T, typename... Ts> 
struct print_impl<T, Ts...> { 
    static void run() { 
     std::cout << 1 << "\n"; 
     print_impl<Ts...>::run(); 
    } 
}; 

template <typename... Ts> 
void print() { 
    print_impl<Ts...>::run(); 
} 

int main() { 
    print<int, int, int>(); 
    return 0; 
} 
+0

Ich denke, die Komplexität hier ist nicht verdient. Die Lösung von n.m. ist viel einfacher. – bames53