什么是 SFINAE

SFINAE 代表 S ubstitution F ailure I s N ot A n E rror。通过替换类型(或值)来实例化函数模板或类模板产生的错误代码不是硬编译错误,它仅被视为演绎失败。

实例化函数模板或类模板特化时的扣除失败会从考虑因素中删除该候选者 - 就好像该失败的候选者不存在一样。

template <class T>
auto begin(T& c) -> decltype(c.begin()) { return c.begin(); }

template <class T, size_t N>
T* begin(T (&arr)[N]) { return arr; }

int vals[10];
begin(vals); // OK. The first function template substitution fails because
             // vals.begin() is ill-formed. This is not an error! That function
             // is just removed from consideration as a viable overload candidate,
             // leaving us with the array overload. 

只有直接上下文中的替换失败才被视为演绎失败,所有其他失败都被视为硬错误。

template <class T>
void add_one(T& val) { val += 1; }

int i = 4;
add_one(i); // ok

std::string msg = "Hello";
add_one(msg); // error. msg += 1 is ill-formed for std::string, but this
              // failure is NOT in the immediate context of substituting T