template<bool F, typename = std::enable_if_t<F>>
auto func1() -> int { return 0; }
template<bool F, typename = std::enable_if_t<!F>>
auto func1() -> int { return 0; }
template<bool F, std::enable_if_t<F, int> = 0>
auto func2() -> int { return 0; }
template<bool F, std::enable_if_t<!F, int> = 0>
auto func2() -> int { return 0; }
有两组重载函数:func1()
和func2()
。func1()
使用SFINAE类型参数,func2()
使用SFINAE非类型参数
编译这些函数时,func1()
会导致编译错误,而func2()
不会。为什么SFINAE对func2()
有效而对func1()
无效?
因为在第一种情况下,SFINAE失败只会删除模板参数的默认值。
// in case F is true, you have
template <bool F, typename = void>
int func1() { return 0; }
template <bool F, typename> // no more default but still available
int func1() { return 0; }
So并没有禁用这个函数,而且你对同一个函数有两个定义(默认值不会改变函数签名),所以,正如Jarod42指出的那样(谢谢),你违反了一个定义规则。
在第二种情况下,您删除了模板形参,因此您销毁了函数,因此不再存在冲突。
template <bool F, int = 0>
int func2() { return 0; }
// template<bool F, ...> // function removed
// int func2() { return 0; }
您可以验证,在第一种情况下,也是"disabled"函数仍然可用,使用单个函数进行测试
template <bool F, typename = std::enable_if_t<F>>
int foo ()
{ return 0; }
用true
、false
和false, void
调用。
foo<true>(); // compile: foo<true, void>() called
foo<false>(); // compilation error: no second template paramenter
foo<false, void>(); // compile: explicit second template parameter