constexpr结构成员初始化 [英] constexpr struct member initialisation
问题描述
此代码编译:
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 ofe
, 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屋!