2016-04-07 13 views
1

Ich versuche das Konzept der variadischen Vorlagen zu erfassen und zu verstehen. Ich kam in this BeispielVariadic Templates Beispiel nicht kompilieren

#include <iostream> 
using namespace std; 

//Output function to output any type without type specifiers like printf() family 
template <typename T, typename ...P> 
void output(T t, P ...p) 
{ 
    cout << t << ' '; 
    if (sizeof...(p)) { output(p...); } 
    else { cout << '\n'; } 
} 

//Since variadic templates are recursive, must have a base case 
void output() { cout << "\n"; } 

//Test it 
int main() 
{ 
    //output(); 
    output('5', 2); 

    return(0); 
} 

aber wenn ich versuche, es zu laufen bekomme ich die Fehler

main.cpp: In instantiation of 'void output(T, P ...) [with T = int; P = {}]': 
main.cpp:10:29: required from 'void output(T, P ...) [with T = char; P = {int}]' 
main.cpp:21:16: required from here 
main.cpp:10:29: error: no matching function for call to 'output()' 
    if (sizeof...(p)) { output(p...); } 
          ^
main.cpp:7:6: note: candidate: template<class T, class ... P> void output(T, P ...) 
void output(T t, P ...p) 
    ^
main.cpp:7:6: note: template argument deduction/substitution failed: 
main.cpp:10:29: note: candidate expects at least 1 argument, 0 provided 
    if (sizeof...(p)) { output(p...); } 
          ^

Vorschläge, wie ich das Problem beheben kann. Dank

+3

tauschen die beiden 'output': Eigentlich kann man die Notwendigkeit einer 0 Parameterversion vermeiden Überladungen. –

+0

Das ist nicht _running_, das ist _compiling_. Ich habe mich wirklich gefragt, wie variadic Vorlagen einen Laufzeitfehler verursachen könnten. – MSalters

Antwort

4

Schalten Sie die Reihenfolge der Deklaration Ihrer Ausgabefunktionen:

//Since variadic templates are recursive, must have a base case 
void output() { cout << "\n"; } 

//Output function to output any type without type specifiers like printf() family 
template <typename T, typename ...P> 
void output(T t, P ...p) 
{ 
    cout << t << ' '; 
    if (sizeof...(p)) { output(p...); } 
    else { cout << '\n'; } 
} 

Die Überladungsauflösung Regeln flippig erhalten für Template-Funktionen, so dass der Compiler als nur die Überlastungen, die bisher erklärt worden war, und tat es nicht Betrachten Sie Ihre Nicht-Vorlage. Beim Schreiben mehrerer Überladungen, bei denen eine oder mehrere Vorlagenfunktionen verwendet werden, spielt die Reihenfolge der Deklaration eine Rolle.

+0

Können Sie erklären, was vor sich geht? – MistyD

+0

Vielen Dank für die Klärung dieser – MistyD

+2

Deklaration Reihenfolge spielt keine Rolle: http: // ideone.com/2GHhj0 –

1

T t wird das erste Argument und P ...p der Rest sein.

output('5', 2); 
//  ^

Sie setzen die Funktion void output() unten, und es ist nicht sichtbar.

Um dies zu beheben, können Sie die Funktion oben erklären, so dass es zu sehen sein wird:

void output(); 

oder die Funktion ohne Parameter übereinander bewegen:

void output() { cout << "\n"; } 

template <typename T, typename ...P> 
void output(T t, P ...p) { // ... } 
2

Es ist mehr Komplizierter als nur Deklarationsreihenfolge. Sehen Sie diese Antwort: Switch passed type from template

template <typename T, typename ...P> 
void output(T t, P ...p) 
{ 
    cout << t << ' '; 
    if (sizeof...(p)) { output(p...); } // HERE 
    else { cout << '\n'; } 
} 

Unabhängig davon, ob oder nicht, wird die Funktion aufgerufen tatsächlich muss es existieren. Sie können keine Verzweigung innerhalb einer Funktion haben, die, obwohl sie nie ausgeführt wurde, zu einem Syntaxfehler führt. Ihr Scheck für sizeof...(p) ist also irgendwie sinnlos.

So Ihr Code klarer zu machen, dass sie sich äußert vollständig und keine Extramaterial, um dies zu ändern:

void output() { cout << "\n"; } 

//Output function to output any type without type specifiers like printf() family 
template <typename T, typename ...P> 
void output(T t, P ...p) 
{ 
    cout << t << ' '; 
    output(p...); 
} 

Sie sie auch nicht definieren müssen zwar in dieser Reihenfolge, es ist einfacher. Sie können dies tun:

void output(); 

//Output function to output any type without type specifiers like printf() family 
template <typename T, typename ...P> 
void output(T t, P ...p) 
{ 
    cout << t << ' '; 
    output(p...); 
} 

void output() { cout << "\n"; } 

Oder auch dies:

template <typename T, typename ...P> 
void output(T t, P ...p) 
{ 
    void output(); 
    cout << t << ' '; 
    output(p...); 
} 

void output() { cout << "\n"; } 

Edit:

template < typename T > 
void output(T t) { cout << t << "\n"; } 

//Output function to output any type without type specifiers like printf() family 
template <typename T, typename ...P> 
void output(T t, P ...p) 
{ 
    cout << t << ' '; 
    output(p...); 
} 
+2

Der letzte wird nicht funktionieren. Die lokale 'output' Deklaration blendet die Vorlage aus. –

+0

Sie haben Recht. Mein Fehler. Verlassen zu Lernzwecken. –