2012-04-23 30 views
7

Czy mogę używać szablonów variadic bez użycia parametrów szablonu jako parametrów funkcji?Szablony Variadic bez parametrów funkcji

Kiedy ich używać, to kompiluje:

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

Ale kiedy z nich nie korzysta, to nie kompiluje i narzeka dwuznaczności:

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

niestety klas I chcesz podać jako parametry szablonu nie są dostępne (mają statyczne funkcje, które są wywoływane wewnątrz funkcji szablonu). Czy jest jakiś sposób na zrobienie tego?

+1

Jeśli potrzebujesz * unevaluated * ekspresję danego typu, można użyć 'std :: declval ()'. Działa dla dowolnego 'T', niezależnie od tego, czy jest ono możliwe do skonstruowania. –

+4

Co do tego, dlaczego wersja bezargumentowa nie działa: Bez argumentów, oba przeciążenia 'print ' i 'print ' są równie dobre, natomiast z argumentami 'print (3)' jest lepiej dopasowany niż 'print (3, {}) '(gdzie' {} 'oznacza" nic "). Nie stosowanie przeciążeń, jak sugeruje CatPusPus, jest standardową metodą; a ponieważ nie wyprowadzacie swoich argumentów, to jest to najprostsze rozwiązanie. –

+0

Zamierzałem wysłać odpowiedź, ale n.m. już to opublikował. – bames53

Odpowiedz

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

Możesz pozbyć się powielania kodu, wywołując 'print ()' z tej dolnej wersji najbardziej, zamiast powtarzania linii 'cout'. Myślę. –

8

Oznacz to jako 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

Myślę, że złożoność tutaj nie jest wymagana. Rozwiązanie n.m. jest znacznie prostsze. – bames53

Powiązane problemy