constexpr结构成员初始化 [英] constexpr struct member initialisation

查看:163
本文介绍了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 ,例如。来自clang:

The reported error (in MSVC, gcc, and clang) suggests that they think the Info constructor is not defined or is not constexpr, eg. from clang:

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

为什么?

(可能与此问题,但信息应在使用时完成;只有 Foo 仍不完整。)

(Possibly related to this question, but Info should be complete at the point of use; only Foo is still incomplete.)

推荐答案

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

The error message of gcc-8 is arguably more clear:


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


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

It seems the error is produced according to [expr.const] §2:


表达式 e 核心常量表达式,除非对 e 之后,抽象
机器(4.6)的规则,将评估以下表达式之一:

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (4.6), would evaluate one of the following expressions:

...

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

(2.3) — an invocation of an undefined constexpr function or an undefined constexpr constructor;

为什么未定义,

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

The thing is, member function definitions are delayed until the closing brace of the outermost enclosing class (because they can see members of enclosing classes). Consider this class definition:

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;
};

假设这应该起作用,那么实现如何处理此定义?

Assuming this should work, how could an implementation process this definition?

one 是指 Foo ::一个,而不是 :: one ,因此必须在看到该成员之后对其进行处理。它在 two 的定义中使用,它是constexpr,因此必须在该成员的初始化程序之前进行处理。因此,要执行此操作,总订单必须为 one ,然后为 get_one ,然后为 2

one inside Bar::get_one refers to Foo::one, not ::one, so it must be processed after that member is seen. It is used in the definition of two, which is constexpr, so it must be processed before the initialiser of that member. So for this to work, the overall order must be one, then get_one, then two.

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

But C++ implementation don't work this way. They don't do any complicated dependency analysis. They process declarations and definitions in order of being seen, with some exceptions listed in [class.mem] §2.

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

I cannot seem to find an explicit mention in the standard that a constexpr member function is considered undefined until the oitermost enclosing class is complete, but this is the only logical possibility. It cannot work any other way.

这篇关于constexpr结构成员初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆