隐式转换如何适用于非类型模板参数?

Lin*_*gxi 11 c++ templates type-conversion template-specialization implicit-conversion

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

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

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

int main() {
    f<1>();
    f<4>();
    f<0>();
}
Run Code Online (Sandbox Code Playgroud)

我希望int隐式转换到bool这里.但VC,GCC和clang的行为不同.

在VC, ,true,falsefalse打印,这实在是怪我.

在海湾合作委员会,true,true,和false印,这是我的期望.

在clang上,由于语句,代码根本不编译f<4>();.

候选模板被忽略:第一个模板参数的显式指定参数无效

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

Bar*_*rry 14

从标准(§14.3.2/ 5):

对用作非类型模板参数的每个表达式执行以下转换.如果非类型模板参数无法转换为相应模板参数的类型,则程序格式错误.

  • 对于整数或枚举类型的非类型模板参数,将应用转换常量表达式(5.19)中允许的转换.

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

一个积分常量表达式是整体的或无作用域枚举类型的表达式,隐式转换为prvalue,其中所述转换后的表达式是一个核心常量表达式.... 转换后的常量类型表达式T是一个表达式,隐式转换为类型为T的prvalue,其中转换后的表达式是核心常量表达式,隐式转换序列仅包含用户定义的转换,左值到右值转换( 4.1),积分促销(4.5)和积分转换(4.7),而不是缩小转换(8.5.4).[ 注意:这些表达式可以用在新表达式(5.3.4)中,作为case表达式(6.4.2),如果基础类型是固定的(7.2),作为枚举器初始化器,作为数组边界(8.3.4),以及作为整数或枚举非类型模板参数(14.3). - 尾注]

因此,对于整数常量表达式,显式不允许缩小转换(如转换4bool),在这种情况下,这些表达式需要作为非类型模板参数.这使得这个电话f<4>()形成不良.

我相信Clang在发出错误时是正确的,而GCC和VC都不符合未发布任何诊断的要求.

[更新]这是GCC Bug#57891,看起来它目前尚未分配.