当前位置: 首页 > 知识库问答 >
问题:

constexpr结构成员初始化

费和惬
2023-03-14

此代码编译:

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

为什么?

(可能与这个问题有关,但信息在使用时应该是完整的;只有Foo仍然不完整。

共有1个答案

巫新知
2023-03-14

gcc-8 的错误html" target="_blank">消息可以说更清晰:

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

假设这应该可行,那么实现如何处理这个定义呢?

Bar::get_one里面的one指的是Foo::one,而不是::one,所以必须在看到该成员后进行处理。它用在2的定义中,也就是康斯特普布尔,所以必须在该成员的初始化程序之前进行处理。所以为了使其工作,整体顺序必须是one,然后是get_one,然后是2

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

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

 类似资料:
  • 主要内容:使用“键值对”初始化结构体,使用多个值的列表初始化结构体,初始化匿名结构体结构体在实例化时可以直接对成员变量进行初始化,初始化有两种形式分别是以字段“键值对”形式和多个值的列表形式,键值对形式的初始化适合选择性填充字段较多的结构体,多个值的列表形式适合填充字段较少的结构体。 使用“键值对”初始化结构体 结构体可以使用“键值对”(Key value pair)初始化字段,每个“键”(Key)对应结构体中的一个字段,键的“值”(Value)对应字段需要初始化的值。 键值对的

  • 问题内容: 我是Golang的新手,所以分配它会让我发疯: 之后,我打电话给: 这时我得到了nil指针恐慌。 我通过使用另一个函数并在之后调用它来解决该问题: 但是我想知道,是否有可能摆脱这种样板初始化? 问题答案: 您只需要一个构造函数。常用的模式是 如果结构中有更多字段,启动goroutine作为后端或注册终结器,则可以在此构造函数中完成所有操作。

  • 考虑以下代码: GCC v6.1编译它,叮当声3.8拒绝它,错误如下: 2:错误:没有成员名为'foo'在'U' struct S{静态constexpr int bar=T::foo;}; 哪个编译器是对的? 会不会是因为在我们尝试在中使用它时不是一个完整的类型? 在这种情况下,它应该被认为是GCC的错误,但我想知道我是否正确之前在错误跟踪器上搜索/打开问题… 编辑 与此同时,我已经向GCC打开

  • 问题内容: 我最近刚与Python中的一个错误作斗争。那是那些愚蠢的新手错误之一,但是它让我思考了Python的机制(我是C ++的老程序员,是Python的新手)。我将列出错误的代码并解释如何解决该问题,然后我有两个问题。 场景:我有一个叫做A的类,它有一个字典数据成员,下面是其代码(当然这是简化的): 使用此代码的类为B类: 请注意,每次调用都会初始化类A的新“干净”实例,并在添加前后打印字典

  • 本文向大家介绍Visual Basic .NET成员初始化,包括了Visual Basic .NET成员初始化的使用技巧和注意事项,需要的朋友参考一下 示例 每个枚举成员可以用一个值初始化。如果未为成员指定值,则默认情况下将其初始化为0(如果它是成员列表中的第一个成员),或者初始化为比前一个成员的值大1的值。            

  • 问题内容: 我不知道如何初始化嵌套结构。在此处找到示例:http: //play.golang.org/p/NL6VXdHrjh 问题答案: 好吧,有什么特定的原因不使Proxy成为自己的结构? 无论如何,您有2个选择: 正确的方法是,只需将proxy移至其自己的结构,例如: 不太正确和丑陋的方法,但仍然有效: