非类型模板参数的隐式转换如何工作?

How implicit conversion works for non-type template parameters?

我猜(某些)隐式转换在传递非类型模板参数时适用。例如,对于像 std::array<int, 7> 这样的表达式,应该有从 intstd::size_t 的转换。但是,请考虑以下代码:

template <bool>
void f() {
    std::cout << "false\n";
}

template <>
void f<true>() {
    std::cout << "true\n";
}

int main() {
    f<1>();
    f<4>();
    f<0>();
}

我希望 int 在这里隐式转换为 bool。但是 VC、GCC 和 clang 上的行为不同。

在VC上打印了truefalsefalse,这让我很奇怪。

在 GCC 上,打印了 truetruefalse,这正是我所期望的。

在 clang 上,由于 f<4>();.

语句,代码根本无法编译

candidate template ignored: invalid explicitly-specified argument for 1st template parameter

那么,标准对此有何规定?非类型模板参数的隐式转换规则是什么?

来自标准 (§14.3.2/5):

The following conversions are performed on each expression used as a non-type template-argument. If a non-type template-argument cannot be converted to the type of the corresponding template-parameter then the program is ill-formed.

  • For a non-type template-parameter of integral or enumeration type, conversions permitted in a converted constant expression (5.19) are applied.

在 §5.19 中,我们学习(强调我的):

An integral constant expression is an expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. ... A converted constant expression of type T is an expression, implicitly converted to a prvalue of type T, where the converted expression is a core constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (4.1), integral promotions (4.5), and integral conversions (4.7) other than narrowing conversions (8.5.4). [ Note: such expressions may be used in new expressions (5.3.4), as case expressions (6.4.2), as enumerator initializers if the underlying type is fixed (7.2), as array bounds (8.3.4), and as integral or enumeration non-type template arguments (14.3). —end note ]

因此,对于整数常量表达式,明确不允许缩小转换(如将 4 转换为 bool),在这种情况下,整数常量表达式需要作为非类型模板参数。这使得调用 f<4>() 格式错误。

我相信 Clang 发出错误是正确的,而 GCC 和 VC 都因未发出任何诊断而不合格。

[更新] 这是 GCC Bug #57891,看起来它当前未分配。