2013-07-24 34 views
11

据我所知,SFINAE意味着替换失败不会导致编译错误,但只是从可能的重载列表中删除原型。了解SFINAE

我不明白:这是为什么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>{}; 

从我的理解,这里的基本逻辑是相同的。这个问题从this answer的评论中浮现出来。

+5

既不代码SFINAE使用SFINAE。 – jrok

+0

您似乎回答了您自己的问题:SFINAE不会导致编译时错误(如果替换失败),而静态断言的整个目的是导致编译时错误(某些情况并非如此) –

+1

@ jrok维基百科说'enable_if'是SFINAE,它错了吗? – nijansen

回答

12

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

伪参数在这两种情况下,为了得到嵌套式type是做的T替换操作SFINAE的本质。与std::enable_if相反,您的assert模板没有可用于SFINAE的替代部分的嵌套类型

请参阅Jonathan Wakely的优秀ACCU 2013 presentation以了解更多细节以及C++ 11表达式SFINAE。等(如在评论中指出的@BartekBanachewicz)是现在也可以在函数模板默认参数

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

你也可以在模板参数列表中做到这一点。 –

+2

所以'enable_if' **不是** SFINAE,但'typename enable_if :: type' **是** SFINAE,因为如果模板替换失败,它不会导致错误(只要它不是唯一的比赛)? – nijansen

+0

@nijansen正确! – TemplateRex