SFINAE 是关于替代的。那么就让我们来代替吧!
template<
typename T,
std::enable_if_t<std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}
template<
typename T,
std::enable_if_t<!std::is_same<T, int>::value, T>* = nullptr>
void Add(T) {}
Becomes:
template<
class T=int,
int* = nullptr>
void Add(int) {}
template<
class T=int,
Substitution failure* = nullptr>
void Add(int) {
template<
class T=double,
Substitution failure* = nullptr>
void Add(double) {}
template<
class T=double
double* = nullptr>
void Add(double) {}
删除我们得到的失败:
template<
class T=int,
int* = nullptr>
void Add(int) {}
template<
class T=double
double* = nullptr>
void Add(double) {}
Now 删除模板参数值:
template<
class T,
int*>
void Add(T) {}
template<
class T
double*>
void Add(T) {}
这些是不同的模板。
现在搞砸的是:
template<
typename T,
typename = typename std::enable_if<std::is_same<T, int>::value, T>::type>
void Add(T) {}
template<
typename T,
typename = typename std::enable_if<!std::is_same<T, int>::value, T>::type>
void Add(T) {}
Becomes:
template<
typename T=int,
typename =int>
void Add(int) {}
template<
typename int,
typename = Substitution failure >
void Add(int) {}
template<
typename T=double,
typename = Substitution failure >
void Add(double) {}
template<
typename T=double,
typename = double>
void Add(double) {}
排除故障:
template<
typename T=int,
typename =int>
void Add(int) {}
template<
typename T=double,
typename = double>
void Add(double) {}
现在模板参数值:
template<
typename T,
typename>
void Add(T) {}
template<
typename T,
typename>
void Add(T) {}
这些是相同的模板签名。这是不允许的,会产生错误。
为什么会有这样的规定呢?超出了这个答案的范围。我只是展示这两种情况的不同之处,并断言标准以不同的方式对待它们。
当您使用如上所述的非类型模板参数时,您将更改模板签名而不仅仅是模板参数值。当您使用如上所述的类型模板参数时,您只需更改模板参数值。