【问题标题】:C++98 curly brace const scalar initializationC++98 花括号 const 标量初始化
【发布时间】:2013-12-18 16:07:31
【问题描述】:

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

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 并解决了这个问题。

【问题讨论】:

  • 我会说这是编译器中的错误。
  • @Raxvan:这是一个相当大胆的声明......考虑到它在 C++11 中而不是在 C++98 中有效,这似乎是经过深思熟虑的,所以我实际上希望它是 根据规范(在 Clang 部分),并且 gcc 像往常一样更加宽松。
  • @MatthieuM.:我认为这就是他想表达的:它是 gcc 中的一个错误。对此没有 C++98 语法,clang 理所当然地拒绝了它。因此,尽管不是 C++98,但在 gcc 中接受它是一个错误。
  • 我现在正在检查 98 标准以查找所有数据。

标签: c++ gcc clang c++98


【解决方案1】:

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

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

T x = { a };

等价于

T x = a;

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

【讨论】:

    【解决方案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 初始化器 /13

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

    T x = { a };

    等价于

    T x = a;

    现在基于this postconst intint 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

    【讨论】:

      【解决方案3】:

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

      在标准的第 14 段中写道:

      初始化器用大括号括起来时没有定义源类型 或者当它是一个带括号的表达式列表时

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-30
        • 1970-01-01
        • 2019-02-04
        • 2020-05-14
        相关资源
        最近更新 更多