2016-01-27 5 views

Odpowiedz

17

Kiedy pozwala na awarię podstawienia bez twardego błędu (jak static_assert).

np

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

Funkcja jest zgłaszana do wszystkich T, nawet tych z nie mają f, więc nie można zrobić SFINAE na call_f<WithoutF> jako metoda istnieje. (Demo kodu, który nie jest kompilowany).

z następującymi zmianami:

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

Sposób istnieje tylko dla ważnego T. więc można użyć SFINAE jak

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); 
} 

Zanotować int = 0 i ... jest zamówienie przeciążenia. Demo

-

Innym przypadkiem jest gdy szablon dodać specjalny parametr stosowania SFINAE dla specjalizacji:

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

A potem

// 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

Czy 'int = 0' kontra' ... 'nie jest wieloznaczny? – TartanLlama

+1

Co masz na myśli przez: * nie możesz zrobić SFINAE na 'call_f ' *? –

+0

@TartanLlama nie, nie dlatego, że 'int' jest bardziej wyspecjalizowany__ niż' ... – tkausl

4

Jednostka jest określany SFINAE- przyjazny, jeśli można go użyć w kontekście SFINAE, nie powodując poważnego błędu po niepowodzeniu substytucji. Zakładam, że już wiesz, czym jest SFINAE, ponieważ jest to zupełnie inne pytanie samo w sobie.

W kontekście standaryzacji C++ termin przyjazny dla SFINAE został dotychczas zastosowany do std::result_of i std::common_type. Weźmy następujący przykład:

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")); 
} 

Bez SFINAE przyjaznej common_type, byłoby to nie skompilować, ponieważ std::common_type<std::string, int>::type przyniosłoby twardy błąd podczas zastępowania szablon argumentów. Po wprowadzeniu przyjaznego dla SFINAE modelu common_type (N3843) ten przykład staje się dobrze sformułowany, ponieważ std::common_type<std::string, int>::type powoduje niepowodzenie substytucji, tak że przeciążenie jest wykluczone z realnego zestawu.

Oto podobny przykład z 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); 
} 

Bez SFINAE przyjazne result_of, byłoby to nie skompilować, ponieważ std::result_of<int()>::type przyniosłoby twardy błąd podczas zastępowania szablon argumentów. Po wprowadzeniu przyjaznego dla SFINAE result_of (N3462) ten przykład staje się dobrze uformowany, ponieważ std::result_of<int()>::type powoduje niepowodzenie substytucji, tak że przeciążenie jest wykluczone z realnego zestawu.