2013-07-24 20 views
11

Z tego co wiem, SFINAE oznacza, że ​​awarie substytucji nie powodują błędów kompilacji, a jedynie usunięcie prototypu z listy możliwych przeciążeń.Zrozumieć SFINAE

Co ja nie rozumiem: dlaczego jest to SFINAE:

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

Ale to nie jest?

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

Z tego co wiem, logika leżąca u podstaw jest tutaj identyczna. To pytanie pojawiło się w komentarzach do this answer.

+5

Żaden z tych kodów nie jest SFINAE. – jrok

+0

Wygląda na to, że odpowiadasz na własne pytanie: SFINAE robi _nie_ powoduje błąd podczas kompilacji (jeśli podstawianie się nie powiedzie), podczas gdy cały cel asercji statycznej _jest_ powoduje błąd kompilacji (jeśli jakiś warunek nie jest prawdziwy) –

+1

@ Wikipedia mówi, że 'enable_if' to SFINAE, czy to źle? – nijansen

Odpowiedz

12

w C++ 98, SFINAE odbywa się z każdym typem powrotnego lub manekina argumentu funkcja jest z domyślnym parametrem

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

W obu przypadkach substution z T aby uzyskać typu zagnieżdżonego type jest istota SFINAE. W przeciwieństwie do std::enable_if, twój szablon assert ma nie ma zagnieżdżonego typu, który może być użyty w części zastępującej SFINAE.

Zobacz znakomity ACCU 2013 presentation Jonathana Wakely'ego, aby uzyskać więcej szczegółów, a także wyrażenie SFINAE w C++ 11. Między innymi (jak zauważył w komentarzach @BartekBanachewicz) można teraz używać SFINAE w szablonach domyślnych argumentów funkcji

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

Możesz także zrobić to na liście szablonów. –

+2

Tak więc 'enable_if' ** nie jest ** SFINAE, ale' nazwa_pliku enable_if :: type' ** jest ** SFINAE, ponieważ nie doprowadzi do błędu, jeśli zastępowanie szablonu się nie powiedzie (o ile nie jest to jedyne mecz)? – nijansen

+0

@nijansen correct! – TemplateRex