【问题标题】:constexpr struct member initialisationconstexpr 结构成员初始化
【发布时间】:2019-02-13 00:50:21
【问题描述】:

这段代码编译:

struct Info
{
    constexpr Info(bool val) : counted(false), value(unsigned(val)) {}
    constexpr Info(unsigned val) : counted(true), value(val) {}

    bool counted;
    unsigned value;
};

constexpr const auto data = std::array{
    Info{true}, Info{42u}
};

struct Foo
{
    constexpr static inline const auto data = std::array{
        Info{true}, Info{42u}
    };
};

这段代码没有:

struct Foo
{
    struct Info
    {
        constexpr Info(bool val) : counted(false), value(unsigned(val)) {}
        constexpr Info(unsigned val) : counted(true), value(val) {}

        bool counted;
        unsigned value;
    };

    constexpr static inline const auto data = std::array{
        Info{true}, Info{42u}
    };
};

报告的错误(在 MSVC、gcc 和 clang 中)表明他们认为 Info 构造函数未定义或不是 constexpr,例如。来自铿锵声:

prog.cc:21:5: note: undefined constructor 'Info' cannot be used in a constant expression
    Info{true}, Info{42u}
    ^

为什么?

(可能与this question 相关,但Info 在使用时应该是完整的;只有Foo 仍然不完整。)

【问题讨论】:

标签: c++ c++17 constexpr


【解决方案1】:

gcc-8的错误信息可以说更清楚了:

   constexpr Foo::Info::Info(bool)’ called in a constant expression before 
   its definition is complete

似乎错误是根据 [expr.const] §2 产生的:

表达式e 是一个核心常量表达式,除非e 的求值遵循抽象规则 machine (4.6),将评估以下表达式之一:

...

(2.3) — 调用未定义的 constexpr 函数或未定义的 constexpr 构造函数;

当调用明确定义之后,为什么它是未定义的?

问题是,成员函数定义被延迟到最外层封闭类的右大括号(因为它们可以看到封闭类的成员)。考虑这个类定义:

constexpr int one = 1;

struct Foo
{
    struct Bar
    {
        static constexpr int get_one() { return one; }
    };

    static constexpr int two = Bar::get_one() + 1;
    static constexpr int one = 42;
};

假设这应该可行,实现如何处理此定义?

one里面Bar::get_one指的是Foo::one,而不是::one,所以必须在看到那个成员之后再处理。用在two的定义中,也就是constexpr,所以必须在那个成员的初始化器之前处理。因此,要使其正常工作,总顺序必须是 one,然后是 get_one,然后是 two

但是 C++ 实现不能以这种方式工作。他们不做任何复杂的依赖分析。它们按照被看到的顺序处理声明和定义,[class.mem] §2 中列出了一些例外情况。

我似乎无法在标准中找到明确提及 constexpr 成员函数在最接近的封闭类完成之前被认为是未定义的,但这是唯一合乎逻辑的可能性。它不能以任何其他方式工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 2020-09-30
    相关资源
    最近更新 更多