【问题标题】:How do I forward-declare a constexpr object at namespace scope?如何在命名空间范围内前向声明 constexpr 对象?
【发布时间】:2013-11-13 16:16:13
【问题描述】:

在 clang(主干)上,我可以转发声明一个稍后将使用 constexpr 定义的对象,如下所示:

// Fwd-declarations
struct S;
extern const S s;

// (... later) definitions
struct S {};
constexpr S s {};

Gcc 4.8 不喜欢这样,告诉我前向声明和定义在constexpr-ness 中不同。 gcc 说的是真的,还是这只是 gcc 的错误?

【问题讨论】:

    标签: c++ gcc c++11 clang


    【解决方案1】:

    我在我的 C++11 标准副本中找不到任何明确禁止 constexpr-ness 在声明和定义之间不匹配的语言,但我确实看到了明确禁止 constexpr 的语言与 extern 一起使用(第 7.1.5 节),并且我还看到语言需要类级 static constexpr 变量的初始化程序才能在类中。此外,由于constexpr 的效用在变量的定义或其类型不可用时显着降低,我认为可能的意图是必须定义constexpr 变量(或者,对于static 类成员,初始化) 当它们被声明时。

    作为一种变通方法,也许您可​​以为变量提供一个extern 别名。这将允许您获取它的地址,这是我能想到的唯一的事情是前向声明允许的。例如:

    // .hpp file:
    struct C;
    extern C const &c;
    
    // .cpp file:
    struct C {
        constexpr C() { }
    };
    constexpr C cc;
    C const &c = cc;
    

    旁注:我知道在 C++14 中,他们重新访问/正在重新访问 constexpr,因此它可能在 Clang 中工作,因为它正在实现 C++14 的一些草案规范。

    【讨论】:

    • C++14 草案实现必须使用-std=c++1y 启用;几乎不可能偶然做到这一点。
    • @Griwes 我目前不使用 Clang(不过我想使用),所以我不知道,但这并不让我感到惊讶。但是 Clang 在开发 C++14 时可能已经全面扩展了对constexpr 的支持(以兼容的方式)。我只是把它作为一种可能性扔掉。由于我在标准中找不到任何措辞,可能这两种实现都是 C++11 的有效选择,或者这可能是一个标准缺陷。
    • 好的,听起来像是一个 gcc 错误。我已经提交了here
    • DyP,仅仅因为constexpr必须用在定义上并不意味着你不能前向声明一个对象,它只是意味着constexpr不能出现在前向-宣言。到目前为止,我没有看到任何东西告诉我我的原始代码无效。
    • @AdamH.Peterson 3.1/2:“声明是一个定义,除非……它包含 extern 说明符(7.1.1)……既不是初始化器也不是函数体……”constexpr对象声明需要一个初始化器,extern 只是不放弃该要求,但extern constexpr int q = 3; 仍然有效。
    【解决方案2】:

    真正的答案是 gcc 完全错误,clang 是正确的。上面的代码应该可以编译,它会在 gcc 4.9 中编译。或者说this bug report

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-15
      • 2021-11-09
      • 1970-01-01
      • 2023-03-06
      • 2011-09-20
      • 2011-03-02
      相关资源
      最近更新 更多