enable_if 的语法模式

vpo*_*yev 5 c++ gcc clang language-lawyer enable-if

我一直enable_if以这种近似的方式使用各种版本的 GCC(最高 5.2):

template< bool b, std::enable_if_t< b >... >
void fn() { std::cout << 1 << std::endl; }
template< bool b, std::enable_if_t< !b >... >
void fn() { std::cout << 2 << std::endl; }
// ...
fn< true >();
fn< false >();
Run Code Online (Sandbox Code Playgroud)

但是,事实证明,Clang 3.7 不接受这一点(“调用‘fn’是不明确的”)。

Q1. 谁是对的,为什么?

当然,还有其他方法可以做到这一点,但我有点不喜欢

template< bool b >
std::enable_if_t< b, void > fa() { std::cout << 1 << std::endl; }
// ...
Run Code Online (Sandbox Code Playgroud)

以及它的同类,使函数签名的正常部分变得不那么可读,并且

template< bool b, std::enable_if_t< b, int > = 0 >
void fd() { std::cout << 1 << std::endl; }
// ...
Run Code Online (Sandbox Code Playgroud)

用于涉及不相关的元素(类型和值)。

Q2。还有哪些其他(正确的、更易读的、更少黑客/怪异的)使用enable_if/enable_if_t的方法?

101*_*010 3

根据标准14.1/p7模板参数[temp.param]重点是我的):

非类型模板参数不得声明为具有浮点、类或void 类型

因此,您的代码片段格式不正确。因此,GCC 在这一点上是错误的。

但是,如果您更改为:

template< bool b, std::enable_if_t< b, int>... >
void fn() { std::cout << 1 << std::endl; }
template< bool b, std::enable_if_t< !b, int>... >
void fn() { std::cout << 2 << std::endl; }
Run Code Online (Sandbox Code Playgroud)

限制已解除,该代码是合法的,应该被接受。显然,Clang 似乎也拒绝了这段代码。恕我直言,这是一个 Clang 错误。

据我发现,类似的错误已被报告23840

现在对于实际部分,我不知道这是否实用/不那么黑客/不那么奇怪,但你可以执行以下操作:

template< bool b, std::enable_if_t< b, int> = 0 >
void fn() { std::cout << 1 << std::endl; }
template< bool b, std::enable_if_t< !b, int> = 0 >
void fn() { std::cout << 2 << std::endl; }
Run Code Online (Sandbox Code Playgroud)