此错误消息是否正确:非类型模板参数不是常量表达式

时间:2016-01-02 02:02:34

标签: c++ templates c++11 language-lawyer constexpr

以下程序使用GCC 5.2编译,但不使用clang 3.6:

constexpr bool flag();

template <bool b = flag()>
constexpr bool test() 
{ 
    return b;
}

int main() 
{
}

我用clang得到的错误信息是:

main.cpp:3:20: error: non-type template argument is not a constant expression
template <bool b = flag()>
                   ^~~~~~
main.cpp:3:20: note: undefined function 'flag' cannot be used in a constant expression
main.cpp:1:16: note: declared here
constexpr bool flag();
               ^
main.cpp:4:16: error: no return statement in constexpr function
constexpr bool test() 
               ^

我的问题是:谁是对的?或者,换句话说:该程序是否格式错误?

2 个答案:

答案 0 :(得分:5)

我说铿锵是对的:

来自标准:

[temp.param] 14.1#9

  

9默认模板参数是在模板参数中=后指定的模板参数(14.3)。 [...]

和[temp.arg.nontype] 14.3.2

  

1非类型模板参数的模板参数应为模板参数类型的转换常量表达式(5.20)。

和[expr.const] 5.20

  

2条件表达式e是核心常量表达式,除非按照抽象机器(1.9)的规则评估e将评估以下表达式之一:

     

[...]

     

(2.3) - 调用未定义的constexpr函数或未定义的constexpr构造函数;

由于flag()已声明但未定义,因此它不是常量表达式,并且违反了14.3.2。

答案 1 :(得分:4)

根据ISO C ++ 14标准5.19.2:

  

条件表达式e是核心常量表达式,除非   评估e,遵循抽象机的规则(1.9),   将评估以下表达式之一:

     
      
  • this(5.1.1),但constexpr函数或constexpr构造函数除外,它被评估为e的一部分;
  •   
  • 为文字类,constexpr函数或隐式调用调用除constexpr构造函数之外的函数   一个简单的析构函数(12.4)[注意:过载分辨率(13.3)照常应用 - 结束注释];
  •   
  • 调用未定义的constexpr函数或未定义的constexpr构造函数;
  •   
  • (...)   块引用
  •   

在定义之前进行的任何constexpr函数调用的结果不是常量表达式。

最后似乎是GCC的错误。