SFINAE 使用 std::enable_if:类型参数与非类型参数
SFINAE using std::enable_if: type parameter vs non-type parameter
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; }
因此不会禁用该函数,并且您对同一函数有两个定义(默认值不会更改函数签名)因此,正如 Jarod42(感谢)指出的那样,您违反了One Definition Rule.
在第二种情况下,你删除了一个模板参数,所以你破坏了函数,所以不再有冲突。
template <bool F, int = 0>
int func2() { return 0; }
// template<bool F, ...> // function removed
// int func2() { return 0; }
您可以验证,在第一种情况下,“已禁用”功能仍然可用,使用单个功能进行测试
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
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; }
因此不会禁用该函数,并且您对同一函数有两个定义(默认值不会更改函数签名)因此,正如 Jarod42(感谢)指出的那样,您违反了One Definition Rule.
在第二种情况下,你删除了一个模板参数,所以你破坏了函数,所以不再有冲突。
template <bool F, int = 0>
int func2() { return 0; }
// template<bool F, ...> // function removed
// int func2() { return 0; }
您可以验证,在第一种情况下,“已禁用”功能仍然可用,使用单个功能进行测试
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