2016-01-27 6 views

Antwort

17

Wenn es Substitutionsfehler ohne schweren Fehler erlaubt (wie static_assert).

zum Beispiel

template <typename T> 
void call_f(const T& t) 
{ 
    t.f(); 
} 

Die Funktion ist für alle T erklärt, auch solche mit nicht f haben, so können Sie SFINAE nicht auf call_f<WithoutF> als die Methode nicht existiert. (Demo des nicht kompilierenden Codes).

mit folgenden Änderung:

template <typename T> 
auto call_f(const T& t) ->decltype(t.f(), void()) 
{ 
    t.f(); 
} 

Das Verfahren besteht nur für gültig T. so können Sie SFINAE als

template<typename T> 
auto call_f_if_available_impl(const T& t, int) -> decltype(call_f(t)) 
{ 
    call_f(t); 
} 

template<typename T> 
auto call_f_if_available_impl(const T& t, ...) 
{ 
    // Do nothing; 
} 

template<typename T> 
auto call_f_if_available(const T& t) 
{ 
    call_f_if_available_impl(t, 0); 
} 

Hinweis verwenden die int = 0 und ... sind die Überlastung zu bestellen. Demo

-

Ein anderer Fall ist, wenn die Vorlage Sonder Parameter hinzufügen SFINAE für die Spezialisierung anwenden:

template <typename T, typename Enabler = void> struct S; 

Und dann

// Specialization only available for T which respect the traits. 
template <typename T> 
struct S<T, std::enable_if_t<my_type_trait<T>::value>> 
{ 
}; 
+0

Ist nicht 'int = 0' vs '... 'mehrdeutig? – TartanLlama

+1

Was meinst du mit: * du kannst SFINAE nicht auf 'call_f ' *? –

+0

@TartanLlama nein es ist nicht weil 'int' ist __more specialise__ als' ... ' – tkausl

4

Ein Unternehmen bezeichnet wird SFINAE- freundlich, wenn es im Zusammenhang mit SFINAE verwendet werden kann, ohne einen harten Fehler bei Substitutionsfehlern zu erzeugen. Ich nehme an, Sie wissen bereits, was SFINAE ist, denn das ist eine ganz andere Frage.

Im Rahmen der C++ - Standardisierung wurde der Begriff SFINAE-freundlich bisher auf std::result_of und std::common_type angewendet. Nehmen Sie das folgende Beispiel:

template <typename T> 
void foo(T x, typename std::common_type<T, int>::type y) {} 

void foo(std::string x, std::string y) {} 

int main() 
{ 
    foo(std::string("hello"), std::string("world")); 
} 

Ohne SFINAE freundliche common_type, dies zu kompilieren würde scheitern, weil std::common_type<std::string, int>::type einen harten Fehler bei der Vorlage Argument Substitution erzeugen würde. Mit der Einführung von SFINAE-freundlich common_type (N3843) wird dieses Beispiel wohlgeformt, weil std::common_type<std::string, int>::type einen Substitutionsfehler erzeugt, so dass Überlastung aus dem lebensfähigen Satz ausgeschlossen wird.

Hier ist ein ähnliches Beispiel mit result_of:

template <typename T> 
auto bar(T f) -> typename std::result_of<T()>::type { return f(); } 

void bar(int n) {} 

int main() 
{ 
    bar(42); 
} 

Ohne SFINAE freundliche result_of, dies zu kompilieren würde scheitern, weil std::result_of<int()>::type einen harten Fehler bei der Vorlage Argumente Substitution erzeugen würde. Mit der Einführung von SFINAE-freundlich result_of (N3462) wird dieses Beispiel wohlgeformt, weil std::result_of<int()>::type einen Substitutionsfehler erzeugt, so dass Überlastung aus dem lebensfähigen Satz ausgeschlossen wird.