2016-08-18 4 views
4

Ich habe einige variadische Template-Methode, die wie folgt aussieht:C++ Variadische Template-Methode Spezialisierung

template<typename ... Args> 
    void Invoke(const char* funcName, Args ... args) const; 

    template<typename ... Args> 
    void Invoke(const char* funcName, Args ... args) const 
    { 
     SPrimitive params[] = { args ... }; 
     SomeOtherInvoke(funcName, params, sizeof ... (Args)); 
    } 

SPrimitive hier - nur eine einfache Struktur mit einem Konstruktor für jeden primitiven Typ.

Ich möchte eine weitere Invoke-Definition für einen komplexen Typ vornehmen. Und hier ist meine Frage: Ist es möglich, variadic Vorlage Methode Spezialisierung in C++ 11/14 machen? ich so etwas wie dies bedeuten (der Einfachheit halber lässt mein Typ int):

template<int ... Args> 
    void Invoke(const char* funcName, Args ... args) 
    { 
     int params[] = { args ... }; 
     SomeComplexInvoke(funcName, params, sizeof ... (Args)); 
    } 

Hier möchte ich eine Spezialisierung, die alle Parameter Zählung vom Typ int nimmt, so kann ich es einfach so nennen:

Invoke("method", 2, 4 ,9); 
+2

Nicht mit Spezialisierung, aber Sie können mit Überlastung und SFINAE. – Jarod42

+0

aber 'std :: initializer_list ' scheint passender (mit 'Invoke (" Methode "{2, 4, 9})' Syntax). – Jarod42

Antwort

4

Wie @ Jarod42 erwähnt, sollte es nicht mit Spezialisierung erfolgen. In Ihrem Beispiel wollen Sie etwas Besonderes, wenn alle Argumenttypen int sind, also lassen Sie uns eine Vorlage schreiben, die sie prüfen wird:

template<typename ref, typename t, typename ...types> 
struct all_same { 
     static constexpr bool value = std::is_same<ref, t>::value && all_same<ref, types...>::value; 
}; 

template<typename ref, typename t> 
struct all_same<ref, t> { 
     static constexpr bool value = std::is_same<ref, t>::value; 
}; 

Es prüft, ob erste Typargument für alle anderen Typargumente gleich ist. Dann in Invoke sollten wir params Typ auswählen, basierend auf args... Typen:

template<typename ... Args> 
void Invoke(const char* funcName, Args ... args) 
{ 
    using params_type = typename std::conditional<all_same<int, Args...>::value, int, SPrimitive>::type; 
    params_type params[] = { args ... }; 
    SomeOtherInvoke(funcName, params, sizeof ... (Args)); 
} 

nun zum Zwecke der Demonstration wollen wir definieren:

struct SPrimitive{ 
}; 

void SomeOtherInvoke(const char*, SPrimitive*, size_t) { 
     std::cout << "Invoked for SPrimitive\n"; 
} 

void SomeOtherInvoke(const char*, int*, size_t) { 
     std::cout << "Invoked for int\n"; 
} 

und rufen

Invoke("foo", SPrimitive()); 
Invoke("foo", SPrimitive(), SPrimitive()); 
Invoke("foo", 1, 2, 3, 4); 

Die Ausgabe lautet:

Invoked for SPrimitive 
Invoked for SPrimitive 
Invoked for int 

was Sie gefragt haben.

+0

Danke, es ist genau das, wonach ich suche! – Michael

Verwandte Themen