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


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

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

最新更新