2015-05-25 5 views
14

Dies ist definitiv eine triviale Frage, aber ich konnte nicht herausfinden, wie dies zu tun ist.Führen Sie verschiedene Funktionen in Abhängigkeit von Template Parameter Dissequation

Ich habe eine Template-Funktion, sagen template <unsigned int N> void my_function(). Nun, ich habe zwei verschiedene Implementierungen für my_function, die erste sollte verwendet werden, wenn N größer ist als, sagen wir 100, die andere, wenn N ist kleiner als das.

Ich versuchte SFINAE wie folgt zu verwenden:

template <unsigned int N, typename = enable_if <N >= 100> :: type> my_function() 
{ 
    // First implementation 
} 

template <unsigned int N, typename = enable_if <N < 100> :: type> my_function() 
{ 
    // Second implementation 
} 

Aber das ist die gleiche Funktion zweimal erklären. Dann versuchte ich etwas wie

template <unsigned int N, bool = (N >= 100)> my_function(); 

Und dann die beiden Funktionen mit den zwei verschiedenen Werten der boolean implementieren. Kein Erfolg, da es sich um eine Teilspezialisierung handelt.

Dann habe ich versucht, N als Strukturparameter und die bool in den Funktionsaufruf zu wickeln, aber es ist eine Member-Funktion spezialisiert vor der Spezialisierung der Klasse, die nicht getan werden kann.

Gibt es einen vernünftigen Weg, dies zu tun?

Antwort

12

Versuchen Sie stattdessen:

#include <type_traits> 
#include <iostream> 

template <unsigned int N, typename std::enable_if <N >= 100> :: type* = nullptr> 
void my_function() 
{ 
    std::cout << "N >= 100" << std::endl; 
} 

template <unsigned int N, typename std::enable_if <N < 100> :: type* = nullptr> 
void my_function() 
{ 
    std::cout << "N < 100" << std::endl; 
} 

int main() 
{ 
    my_function<42>(); 
    my_function<100>(); 
} 

Template default parameters do not participate in the overload (und damit SFINAE gilt nicht). Auf der anderen Seite, im Snippet oben, der abhängigen Vorlage nicht-Typ-Parameter ist auf der linken Seite der Zuweisung, so SFINAE kicks

2

können Sie SFINAE auf Rückgabetyp verwenden.

template <unsigned int N> 
enable_if_t<(N >= 100)> my_function() 
{ 
    // First implementation 
} 

template <unsigned int N> 
enable_if_t<(N < 100)> my_function() 
{ 
    // Second implementation 
} 

derzeit haben Sie nur template <unsigned int N, typename T> mit unterschiedlichen Standardtypen für T.

Für die Teil-Spezialisierung, die Sie Struktur weiterleiten:

template <unsigned int N, bool = (N >= 100)> 
struct my_function_impl; 

template <unsigned int N> 
struct my_function_impl<N, true> 
{ 
    void operator() const { /* First implementation */} 
}; 

template <unsigned int N> 
struct my_function_impl<N, false> 
{ 
    void operator() const { /* Second implementation */} 
}; 

template <unsigned int N> 
void my_function() { my_function_impl<N>{}(); } 
5

Wenn Sie aus irgendeinem Grund nicht mögen enable_if, Sie immer für Tag Versand gehen kann:

#include <type_traits> 
class low {}; 
class high {}; 
template <int N, class T> 
    void func(T, low) 
    { 
     // version for high N 
    } 
template <int N, class T> 
    void func(T, high) 
    { 
     // version for low N 
    } 
template <int N, class T> 
    void func(T val) 
    { 
     func<N>(val, std::conditional_t<(N>=100), high, low>{}); 
    } 
int main() 
{ 
    func<3>(3.14159); // low version 
    func<256>("Yo"); // high version 
} 

In dieser Fall, könnten wir die Tags auf einfache Dinge wie true_type und false_type beschränken, aber im Allgemeinen könnte dies ein alternativer Ansatz sein.

+0

Ich mag das! Ich werde es nächstes Mal benutzen, danke! –