我偶然发现了我不理解的代码。这是它的简化版本:
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产生以下错误:
$ 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错误跟踪器中打开了ticket。
答案 0 :(得分:5)
是的,根据C ++ 98 8.5 / 13,两个声明都是等效的:
如果
形式的声明T
是标量类型,则表示
T x = { a };
相当于
T x = a;
因此两个变量都是常量,并从常量表达式初始化,所以(据我所见)应该都可以用作常量表达式。
答案 1 :(得分:2)
编译器错误指出"template argument of type 'int' is not an integral constant expression"
int const i = { 42 };
根据98 standard,模板参数应属于此类别:
14.3.2 / 1
非类型非模板模板参数的模板参数应为以下之一:
- 整数或枚举类型的整数常量表达式;或
...
并且整数常量表达式int const i
的定义属于这一类:
5.19常量表达式
整数常量表达式只能包含文字(2.13),枚举数,常量变量或静态 数据成员
和i
的初始化(如Mike Seymour的帖子):
8.5 Initializers / 13
如果T是标量类型,则表示
形式的声明T x = {a};
相当于
T x = a;
现在基于this post const int
和int const
的声明应该是相同的(在标准中找不到这个),使i
成为 const变量即可。因此,无论初始化方法如何,i
的任何用法都应该是一个整型常量表达式。看来clang中有一个bug。检查网络我找不到两个或多或少类似的错误报告:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666539
和
http://lists.cs.uiuc.edu/pipermail/llvmbugs/2011-March/017353.html
答案 2 :(得分:1)
我认为Clang是对的。初始化列表不是表达式。初始化聚合对象和基础对象之间存在差异。初始化POD对象时,可以将每个初始化程序视为const表达式。但是,当您处理基本类型时,初始化列表不是表达式,也不是const表达式。
在标准第14段中写道:
初始化程序是大括号括起来时,未定义源类型 或者当它是带括号的表达式列表
时