2012-04-23 20 views
7

È possibile utilizzare modelli variadici senza utilizzare i parametri del modello come parametri di funzione?Modelli variabili senza parametri di funzione

Quando li uso, si 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); 
} 

Ma quando io non li uso, ma non compila e si lamenta di un'ambiguità:

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

Purtroppo le classi I voglio dare come parametri del template non sono istanziabili (hanno funzioni statiche che sono chiamate all'interno della funzione template). C'è un modo per farlo?

+1

Se avete bisogno di un * * non valutata l'espressione di un determinato tipo, è possibile utilizzare 'std :: declval ()'. Funziona per qualsiasi 'T', anche se non è costruibile. –

+4

Per quanto riguarda il motivo per cui la versione no-argument non funziona: senza argomenti, entrambi gli overload 'print ' e 'print ' sono ugualmente buoni, mentre con gli argomenti 'print (3)' è una corrispondenza migliore di 'stampa (3, {}) '(dove' {} 'significa" nulla "). Non usare sovraccarichi, come suggerisce CatPusPus, è il metodo standard; e dal momento che non stai deducendo i tuoi argomenti comunque è la soluzione più semplice. –

+0

Stavo per pubblicare una risposta ma n. già pubblicato. – bames53

risposta

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

È possibile eliminare la duplicazione del codice richiamando 'print ()' da quella versione in basso, invece di ripetere la riga 'cout'. Credo. –

8

Ne fanno 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

Penso che la complessità qui non sia meritata. La soluzione di n.m. è molto più semplice. – bames53

Problemi correlati