2015-06-19 25 views
5

Stavo leggendo di modelli variadic e ho trovato questo esempio. Il libro menziona che per terminare il processo di ricorsione, viene utilizzata la funzione print(). Non riesco davvero a capire il suo uso. Perché l'autore usa questa funzione vuota print()?non riesco a capire i modelli variadic in C++

void print() // can't get why this function is used 
{ 
} 

template <typename T, typename... Types> 
void print (const T& firstArg, const Types&... args) 
{ 
    std::cout << firstArg << std::endl; // print first argument 
    print(args...); // call print() for remaining arguments 
} 
+0

Dopo aver stampato l'ultimo argomento, la stampa "vuota"() verrà richiamata. – Banan

+2

Capisci le funzioni ricorsive? In caso contrario, i modelli variadici saranno un argomento troppo avanzato. – MSalters

+0

@MSalters ottengo completamente le funzioni ricorsive e ho aggiornato la domanda –

risposta

7

Un'espressione variadica può acquisire 0 argomenti o più.

Prendiamo ad esempio la chiamata print(1). Quindi T acquisisce int e Types = {} - non cattura argomenti. Quindi la chiamata print(args...); si espande a print();, motivo per cui è necessario un caso base.


Non è necessaria la ricorsione. Io uso sempre la seguente funzione debuglog nel mio codice (modificato per le vostre esigenze):

template<typename F, typename ... Args> 
    void 
    print(const F& first, const Args&... args) // At least one argument 
    { 
    std::cout << first << std::endl; 
    int sink[] = 
     { 0, ((void)(std::cout << args << std::endl), 0)... }; 
    (void) sink; 
    } 

Poiché questa funzione variadic richiede almeno un argomento, siete liberi di utilizzare print(void) per quello che ti piace ora.

+0

oh grazie bella spiegazione –

+0

ho aggiornato la domanda –

+1

Sì ... che aggirare la ricorsione rende il codice molto più brutto di avere un po 'di duplicazione del codice. Fortunatamente, C++ 17 avrà espressioni di piegatura – KABoissonneault

3

È ricorsiva perché la parte variadic del modello si riduce ogni chiamata, ad esempio, una chiamata sarebbe ricorsivamente simile a questa

print(1, 2, 3, 4, 5) // firstArg == 1 
         // ...args == 2,3,4,5 

print(2, 3, 4, 5)  // firstArg == 2 
         // ...args == 3,4,5 

print(3, 4, 5)  // firstArg == 3 
         // ...args == 4,5 

print(4, 5)   // firstArg == 4 
         // ...args == 5 

print(5)    // firstArg == 5 
         // ...args == {} 

print() 

Il print() è necessaria come un caso base per quando il variadic la lista è vuota

3

Prendere in considerazione una chiamata alla funzione modello con un singolo argomento.

print(1); 

firstArg sarebbe legarsi al 1 (T = int), e Types... sarebbe legarsi a niente. Un pacchetto argomento variabile è zero o più argomenti.

Pertanto, in questa chiamata:

print(args...); 

args... è un parametro pacchetto vuoto. Così si espande in:

print(); 

Dal momento che il modello di funzione corrisponde a qualsiasi chiamata a stampare con una o più argomenti, è necessario una funzione separata per gestire zero argomenti. Che in questo caso è la funzione banale:

void print() { } 
3

Si supponga il seguente codice:

int a, b, c; 
print(a, b, c); 

il compilatore implicitamente creare il seguente codice:

print(const int& firstArg) 
{ 
    std::cout << firstArg << std::endl; // print first argument 
    print(); // call print() for remaining arguments 
} 

print(const int& firstArg, const int& arg2) 
{ 
    std::cout << firstArg << std::endl; // print first argument 
    print(arg2); // call print() for remaining arguments 
} 

print(const int& firstArg, const int& arg2, const int& arg3) 
{ 
    std::cout << firstArg << std::endl; // print first argument 
    print(arg2, arg3); // call print() for remaining arguments 
} 

come si può vedere nel versione con un solo argomento, il compilatore chiamerà un metodo "print" senza argomenti. Poiché la funzione di stampa variadata richiede SEMPRE almeno un parametro, ciò non corrisponde a ...

+0

L'ultima frase è leggermente errata - probabilmente intendevi "Poiché la ** funzione con ** variadic template SEMPRE [...]". – Hiura

+0

@Hiura: grazie per averlo indicato -> risolto – Daniel

Problemi correlati