2012-04-23 15 views
7

¿Puedo usar plantillas variadic sin usar los parámetros de plantilla como parámetros de función?Plantillas variables sin los parámetros de función

Cuando los utilizo, que compila:

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

Pero cuando no los uso, no compila y se queja de una ambigüedad:

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

Desafortunadamente las clases I Quiero dar como parámetros de plantilla no son instanciables (tienen funciones estáticas que se llaman dentro de la función de plantilla). ¿Hay alguna manera de hacer esto?

+1

Si necesita un * * expresión sin evaluar de un tipo determinado, se puede usar 'std :: declval ()'. Funciona para cualquier 'T', sea o no constructible. –

+4

En cuanto a por qué la versión sin argumento no funciona: Sin argumentos, ambas sobrecargas 'imprimir ' e 'imprimir ' son igualmente buenas, mientras que con argumentos 'imprimir (3)' es una mejor coincidencia que 'imprimir (3, {}) '(donde' {} 'significa" nada "). No utilizar sobrecargas, como sugiere CatPusPus, es el método estándar; y como no deduces tus argumentos de todos modos, es la solución más simple. –

+0

Iba a publicar una respuesta, pero n.m. ya publicado. – bames53

Respuesta

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

Puede deshacerse de la duplicación de código invocando 'print ()' desde la versión más inferior, en lugar de repetir la línea 'cout'. Creo. –

8

Haz que sea un tipo.

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

Creo que la complejidad aquí no es válida. la solución de n.m. es mucho más sencilla. – bames53

Cuestiones relacionadas