2013-12-18 42 views
5

我偶然发现了我不明白的代码。下面是它的一个简化版本:C++ 98大括号const标量初始化

template <int> struct A {}; 

int const i = { 42 }; 
typedef A<i> Ai; 

int const j = 42; 
typedef A<j> Aj; 

此代码在C++ 98模式下编译为GCC,但不在Clang中编译。锵产生以下错误:

$ clang -Wall -Wextra -std=c++98 -c test.cpp 

test.cpp:4:11: error: non-type template argument of type 'int' is not an integral constant expression 
typedef A<i> Ai; 
     ^
test.cpp:4:11: note: initializer of 'i' is not a constant expression 
test.cpp:3:11: note: declared here 
int const i = { 42 }; 
     ^

据我了解有和没有大括号应该是相当于int初始化。 Clang将i初始化为42,但并不认为这是编译时间常量。

此代码在C++ 11模式下编译良好。

是否有原因j被视为编译时间常量,i是不是?或者它仅仅是Clang中的一个错误?

更新:我在LLVM bug跟踪器中打开了一个ticket这个问题。

+0

我会说这是在编译器中的错误。 – Raxvan

+2

@Raxvan:这是一个非常大胆的陈述......考虑到它在C++ 11中工作,而不是在C++ 98中,它似乎是非常慎重的,所以我实际上期望它是*按规格*(在Clang部分) ,并且gcc像往常一样更宽松。 –

+0

@MatthieuM .:我认为这是他想说的:它是一个gcc中的bug。没有C++ 98的语法,clang正确地拒绝它。所以接受它在gcc中,尽管不是C++ 98,是一个错误。 – PlasmaHH

回答

2

编译器错误指出"template argument of type 'int' is not an integral constant expression"int const i = { 42 };

根据98 standard模板参数应属于这一类:

14.3.2/1

A template-argument for a non-type, non-template template-parameter shall be one of:

  • an integral constant-expression of integral or enumeration type; or

...

和积分常数表达式的定义int const i fa LL这一类:

5.19 Constant expressions

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members

并为i初始化(像迈克·西摩后):

8.5 Initializers /13

If T is a scalar type, then a declaration of the form

T x = { a };

is equivalent to

T x = a;

现在基于this postconst intint const声明应该是相同的(找不到这特别在标准中)使得i a const变量。因此,无论初始化方法如何,i的任何用法都应该是一个整型常量表达式。看起来在叮当中有一个错误。检查网络我找不到只有两个或多或少类似的错误报告:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666539

http://lists.cs.uiuc.edu/pipermail/llvmbugs/2011-March/017353.html

5

是的,双方的声明是等价的,每个C++ 98 8.5/13:

If T is a scalar type, then a declaration of the form

T x = { a }; 

is equivalent to

T x = a; 

所以这两个变量是恒定的,并从一个常量表达式初始化,所以(据我所知)应该都可以用作常量表达式。

1

我认为锵是正确的。初始值设定项列表不是表达式。聚集对象和基本对象的初始化有所不同。当一个POD对象被初始化时,每个初始化器都可以被认为是一个const表达式。然而,当你处理基本类型时,初始化器列表不是一个表达式,也不是一个常量表达式。

在标准第14号有写:

The source type is not defined when the initializer is brace-enclosed or when it is a parenthesized list of expressions