2016-01-27 6 views

risposta

17

Quando consente la sostituzione senza errori (come static_assert).

ad esempio

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

La funzione è dichiarata per tutti T, anche quelli con non hanno f, quindi non si può fare SFINAE sul call_f<WithoutF> come metodo esiste. (Demo di codice non compilato).

Con seguente modifica:

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

Il metodo esiste solo per valida T. in modo da poter utilizzare come SFINAE

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

Annotare il int = 0 e ... è quello di ordinare il sovraccarico. Demo

-

Un altro caso è quando il modello aggiunge parametro speciale da applicare SFINAE di specializzazione:

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

E poi

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

Non è 'int = 0' vs' ... 'ambiguo? – TartanLlama

+1

Cosa intendi con: * non puoi fare SFINAE su 'call_f ' *? –

+0

@TartanLlama no non è perché 'int' è __more specializzato__ di' ... ' – tkausl

4

Un'entità viene definito SFINAE- amichevole se può essere utilizzato nel contesto di SFINAE senza produrre un errore grave in caso di fallimento della sostituzione. Presumo che tu sappia già cos'è la SFINAE, poiché è un'intera altra questione in sé.

Nel contesto della standardizzazione C++, il termine SFINAE-friendly è stato finora applicato a std::result_of e std::common_type. Prendiamo il seguente esempio:

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

Senza SFINAE-friendly common_type, questo non riuscirebbe a compilare, perché std::common_type<std::string, int>::type produrrebbe un errore hardware durante la sostituzione del modello argomento. Con l'introduzione di SFINAE common_type (N3843) questo esempio diventa ben formato, poiché std::common_type<std::string, int>::type produce un errore di sostituzione in modo che il sovraccarico venga escluso dal set valido.

Ecco un esempio simile con 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); 
} 

Senza SFINAE-friendly result_of, questo non riuscirebbe a compilare, perché std::result_of<int()>::type produrrebbe un errore hardware durante la sostituzione del modello argomento. Con l'introduzione di SFINAE result_of (N3462) questo esempio diventa ben formato, perché std::result_of<int()>::type produce un errore di sostituzione in modo che il sovraccarico sia escluso dal set fattibile.

Problemi correlati