Насколько я знаю, SFINAE означает, что сбои замещения не приводят к ошибкам компиляции, а просто удаляют прототип из списка возможных перегрузок.
Что я не понимаю: почему это СФИНА?
template <bool C, typename T = void> struct enable_if{};
template <typename T> struct enable_if<true, T> { typedef T type; };
Но это не так?
template <bool C> struct assert;
template <> struct assert<true>{};
Насколько я понимаю, основная логика здесь идентична. Этот вопрос возник из комментариев к этот ответ.
В C ++ 98 SFINAE выполняется либо с типом возврата, либо с фиктивным аргументом функции с параметром по умолчанию
// 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);
В обоих случаях замена T
чтобы получить вложенный тип type
это сущность SFINAE. В отличие от std::enable_if
, ваш assert
шаблон делает не имеет вложенного типа которые могут быть использованы в замещающей части SFINAE.
Смотрите отлично Джонатана Уэйкли Презентация ACCU 2013 для более подробной информации, а также для C ++ 11 выражения SFINAE. Среди прочего (как отметил @BartekBanachewicz в комментариях) теперь также возможно использовать SFINAE в аргументах шаблона функции по умолчанию
// 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&);
Других решений пока нет …