我猜(某些)隐式转换在传递非类型模板参数时适用。例如,应该有转换 int
至 std::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>();
}
我预计 int
被隐式转换为 bool
这里。但VC,GCC和clang的行为有所不同。
在VC上, true
, false
,和 false
印刷,这对我来说真的很奇怪。
在海湾合作委员会 true
, true
,和 false
印刷,这是我所期待的。
在clang上,由于语句,代码根本不编译 f<4>();
。
候选模板被忽略:第一个模板参数的显式指定参数无效
那么,标准对此有何看法?非类型模板参数的隐式转换规则是什么?
从标准(§14.3.2/ 5):
对用作非类型的每个表达式执行以下转换 模板参数。如果一个
非类型 模板参数 无法转换为相应的类型 模板参数 然后
该计划格式不正确。
- 对于非类型 模板参数 对于整数或枚举类型,应用转换常量表达式(5.19)中允许的转换。
在§5.19中,我们学习(强调我的):
一个 积分常数表达式 是隐式转换的整数或无范围枚举类型的表达式
到prvalue,其中转换的表达式是核心常量表达式。 ... 一个 转换常量表达式 的
类型 T
是一个表达式,隐式转换为类型为T的prvalue,其中转换后的表达式是一个核心
常量表达式和隐式转换序列仅包含用户定义的转换,lvalue-to-rvalue
转化(4.1),整体促销(4.5)和整体转化(4.7) 除了缩小转换率
(8.5.4)。 [ 注意: 这些表达式可以用在新表达式(5.3.4)中,作为案例表达式(6.4.2),
如果基础类型是固定的(7.2),数组边界(8.3.4),以及整数或
枚举非类型模板参数(14.3)。 - 尾注]
如此缩小转换(如转换 4
至 bool
明确禁止使用整数常量表达式,在这种情况下,它必须作为非类型模板参数。这就是电话 f<4>()
病态的。
我相信Clang在发出错误时是正确的,而GCC和VC都不符合未发布任何诊断的要求。
[更新]这是 GCC Bug#57891,看起来它目前尚未分配。