constexpr结构成员初始化

时间:2019-02-13 00:50:21

标签: c++ c++17 constexpr

此代码编译:

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,例如。来自c声:

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

为什么?

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

1 个答案:

答案 0 :(得分:4)

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

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

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

  

表达式e核心常量表达式,除非遵循抽象规则对e进行求值   机器(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,因此必须在看到该成员之后对其进行处理。它在constexpr的two的定义中使用,因此必须在该成员的初始化程序之前进行处理。因此,要使其正常工作,总顺序必须为one,然后依次为get_onetwo

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

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

相关问题