5

我偶然发现了我不明白的代码。这是它的简化版本:

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带和不带花括号的初始化应该是等效的。Clangi正确初始化为42,只是不认为它是编译时间常数。

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

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

更新:我在 LLVM 错误跟踪器中为这个问题打开了一张票。

4

3 回答 3

6

是的,根据 C++98 8.5/13,这两个声明是等效的:

如果T是标量类型,则声明形式

T x = { a };

相当于

T x = a;

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

于 2013-12-18T16:27:04.773 回答
2

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

根据98 标准,模板参数应该属于这一类:

14.3.2 / 1

非类型、非模板模板参数的模板参数应为以下之一:

  • 整数或枚举类型的整数常量表达式;或者

...

而整型常量表达式的定义就int const i属于这一类:

5.19 常量表达式

整型常量表达式只能涉及文字 (2.13)、枚举器、常量变量或静态数据成员

以及初始化i(如 Mike Seymour 的帖子):

8.5 初始化器 /13

如果 T 是标量类型,则声明形式为

T x = { 一 };

相当于

T x = a;

现在基于这篇文章const int, and的声明int const应该是相同的(在标准中找不到这个具体的)制作i一个const 变量。所以无论初始化方法如何,任何用法都i应该是一个整数常量表达式。看来clang中有一个错误。检查网络我找不到只有两个或多或少相似的错误报告:

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

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

于 2013-12-18T17:45:55.323 回答
1

我认为 Clang 是对的。初始化列表不是表达式。聚合对象的初始化和基本对象的初始化是有区别的。当一个 POD 对象被初始化时,每个初始化器都可以被认为是一个 const 表达式。但是,当您处理基本类型时,初始化列表不是表达式,也不是 const 表达式。

在标准的第 14 段中写道:

当初始化器用大括号括起来或它是带括号的表达式列表时,未定义源类型

于 2013-12-18T16:50:23.717 回答