SFINAE 使用 std::enable_if:类型参数 vs 非类型参数

时间:2021-02-08 12:01:02

标签: c++ templates sfinae non-type-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() 无效?

1 个答案:

答案 0 :(得分:1)

因为在第一种情况下,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(谢谢)所指出的那样,您违反了 {{ 3}}。

在第二种情况下,您删除了模板参数,因此您销毁了该函数,因此不再发生冲突。

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; }

并使用 truefalsefalse, void 调用它。

foo<true>();  // compile: foo<true, void>() called
foo<false>();  // compilation error: no second template paramenter
foo<false, void>();  // compile: explicit second template parameter