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

时间:2015-01-28 04:55:21

标签: c++ templates type-conversion implicit-conversion template-specialization

我猜(某些)隐式转换在传递非类型模板参数时适用。例如,对于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上,会打印truefalsefalse,这对我来说真的很奇怪。

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

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

  忽略

候选模板:第一个模板参数

的显式指定参数无效

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

1 个答案:

答案 0 :(得分:14)

从标准(§14.3.2/ 5):

  

对用作非类型模板参数的每个表达式执行以下转换。如果一个   非类型 template-argument 无法转换为相应 template-parameter 的类型   该计划格式不正确。

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

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

  

整数常量表达式是整数或无范围枚举类型的表达式,隐式转换   到prvalue,其中转换的表达式是核心常量表达式。 ...一个转换的常量表达式   type T是一个表达式,隐式转换为类型为T的prvalue,其中转换后的表达式是一个核心   常量表达式和隐式转换序列仅包含用户定义的转换,lvalue-to-rvalue   转化(4.1),整体促销(4.5)和整数转化(4.7)除了缩小转化次数   (8.5.4)即可。 [注意:这样的表达式可以用在新表达式(5.3.4)中,作为case表达式(6.4.2),   如果基础类型是固定的(7.2),作为数组边界(8.3.4),还是作为整数或者,则作为枚举器初始值设定项   枚举非类型模板参数(14.3)。 -end note]

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

我相信Clang在发出错误方面是正确的,GCC和VC都不符合未发布任何诊断的信息。

[更新]这是GCC Bug #57891,看起来好像是未分配的。