2013-07-24 23 views
11

Per quanto ne so, SFINAE significa che i guasti di sostituzione non provocano errori di compilazione, ma rimuovono il prototipo dall'elenco di possibili sovraccarichi.Informazioni su SFINAE

Quello che non capisco: perché è questo SFINAE:

template <bool C, typename T = void> struct enable_if{}; 
template <typename T> struct enable_if<true, T> { typedef T type; }; 

Ma questo non è?

template <bool C> struct assert; 
template <> struct assert<true>{}; 

Dalla mia comprensione, la logica sottostante è identica qui. Questa domanda è emersa dai commenti a this answer.

+5

Né il codice è SFINAE. – jrok

+0

Sembra che tu risponda alla tua stessa domanda: SFINAE non causa un errore in fase di compilazione (se la sostituzione fallisce), mentre l'intero scopo di un'asserzione statica _is_ causare un errore in fase di compilazione (alcune condizioni non sono vere) –

+1

@ jrok Wikipedia dice 'enable_if' è SFINAE, è sbagliato? – nijansen

risposta

12

In C++ 98, SFINAE avviene ad un tipo di ritorno o argomento fittizio di una funzione con parametro predefinito

// SFINAE on return type for functions with fixed arguments (e.g. operator overloading) 
template<class T> 
typename std::enable_if< std::is_integral<T>::value, void>::type 
my_function(T const&); 

// SFINAE on dummy argument with default parameter for functions with no return type (e.g. constructors) 
template<class T> 
void my_function(T const&, std::enable_if< std::is_integral<T>::value, void>::type* = nullptr); 

In entrambi i casi, substution di T al fine di ottenere il tipo annidato type è il essenza di SFINAE. A differenza di std::enable_if, il modello assert non ha non un tipo nidificato che può essere utilizzato nella parte di sostituzione di SFINAE.

Vedere l'eccellente ACCU 2013 presentation di Jonathan Wakely per ulteriori dettagli e anche per l'espressione CINAE di C++ 11. Tra gli altri (come sottolineato da @BartekBanachewicz nei commenti) è ora è anche possibile utilizzare SFINAE nel modello di funzione argomenti di default

// use C++11 default function arguments, no clutter in function's signature! 
template<class T, class dummy = typename std::enable_if< std::is_integral<T>::value, void>::type> 
void my_function(T const&); 
+0

Puoi anche farlo nell'elenco dei modelli. –

+2

Quindi 'enable_if' ** non è ** SFINAE, ma' typename enable_if :: type' ** è ** SFINAE, perché non causerà un errore se la sostituzione del modello fallisce (a patto che non sia l'unica incontro)? – nijansen

+0

@nijansen corretto! – TemplateRex