2017-01-24 7 views
1

wollte ich eine generische Art und Weise Funktionen zu verarbeiten und schließlich nennt so schrieb ich den Code unter dem Problem, dass der Code kompiliert wird, aber wenn ich es getestet bekomme ich Fehler von Artvariadische Vorlage Spezialisierung Ausgabe

falsch Anzahl der Vorlagenargumente (1, sollte 0 sein) auto al = action :: apply < 5> :: value;

so weiß ich, dass ich etwas falsch mache, aber ich konnte nicht herausfinden, was es ist.

template<typename T, typename enabled=void, typename ...P> 
struct action{ 
    template<P... args> 
    struct apply{ }; 
}; 

template<typename FN,typename ...P> 
struct action<FN, typename std::enable_if< std::is_function<FN>::value >::type ,P...>{ 
    template<P... args> 
    struct apply{ 
     static const decltype(std::result_of<FN(P...)>::type) value = FN(std::forward<P>(args)...); 
    }; 
}; 


int test(int x) 
{ 
    return x; 
} 

int main() 
{ 
    auto al= action<decltype(test), int>::apply<5>::value; 
    std::cout << "result :" << al <<std::endl; 
    return 0; 
} 

Antwort

8

Dies ist Ihre primäre Vorlage:

template<typename T, typename enabled=void, typename ...P> 
struct action 

Wann immer Sie action<blah> tun, die Argumente über diese Primärtemplats interpretiert werden.

action<decltype(test), int> 

so hier, übergeben Sie decltype(test) als T und int als enabled. Und nichts als ...P.

Wir testen dann, ob irgendwelche der Template-Spezialisierungen gelten.

template<typename FN,typename ...P> 
struct action<FN, typename std::enable_if< std::is_function<FN>::value >::type ,P...> 

Dies erfordert eine Untergliederung. Der Teil nachaction ist, was wir Muster gegen übereinstimmen. Der Teil vor ist nur einige Variablen, die wir daraus ableiten.

So

action<decltype(test), int> 
struct action<FN, typename std::enable_if< std::is_function<FN>::value >::type ,P...> 

Linie ihnen:

 action<decltype(test), int> 
struct action<FN   , typename std::enable_if< std::is_function<FN>::value >::type ,P...> 

und hier sind, wie sie entsprechen:

FN=decltype(test) 
typename std::enable_if< std::is_function<FN>::value >::type=int 
P...= 

Ok, also Argument 1 ist decltype(test), aka int(int). Wir folgern dies zu FN. Alles gut.

Als nächstes gibt es 2 Argumente. So ist ...P deutlich leer.

Argument 2 ist in einem nicht-abgeleiteten Zusammenhang. Wir werden es berechnet:

typename std::enable_if< std::is_function<FN>::value >::type 
typename std::enable_if< std::is_function<int(int)>::value >::type 
typename std::enable_if<true>::type 
void 

... na ja, diese Spezialisierung sagt es void ist. Aber wir haben int passiert. Da void=int Unsinn ist, gilt diese Spezialisierung nicht. Wir haben hier keine Übereinstimmung gefunden.

So gehen wir zurück in die primäre Spezialisierung:

template<typename T, typename enabled=void, typename ...P> 
struct action{ 
    template<P... args> 
    struct apply{ }; 
}; 

ok, so hat es ein Mitglied Vorlage apply, dass ... Fertig 0 nicht-Typ Argumente, weil ...P leer.

Daher Ihr Fehler.

Spezialisierungen sind keine Überladungen. Sie sind Mustervergleichsimplementierungen der primären Vorlage. Die primären Vorlagenargumente sind immer die Signatur. Die Spezialisierung kann bestimmte Optionen umbenennen und mit Mustern vergleichen.

Sie möchten wahrscheinlich einen Alias ​​verwenden. Benennen Sie action in action_helper um. Fügen Sie es optional in einen details Namensraum ein. Dann:

template<class T, class...P> 
using action = action_helper<T,void,P...>; 

und verwenden Sie action in Client-Code.

+0

++ für die detaillierte Antwort und danke für den Zeiger –

Verwandte Themen