我可以引用初始值设定项列表的先前成员吗? [英] Can I Reference Previous Members of an Initializer List?

查看:28
本文介绍了我可以引用初始值设定项列表的先前成员吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我想引用我已经定义的 initializer_list 的成员.我可以吗?

Say I want to refer to a member of an initializer_list that I already defined. Can I do it?

此代码在 Visual Studio 和 gcc 中编译并给出预期值:13 55",我会只是想知道这是合法的:

This code compiles and gives the expected: "13 55 " in both Visual Studio and gcc, I'd just like to know that it's legal:

const int foo[2] = {13, foo[0] + 42};

推荐答案

所以我们这里有 C++ 标准草案的 8.5.1 部分涵盖的聚合初始化,它说:

So what we have here is aggregate initialization covered in section 8.5.1 of the draft C++ standard and it says:

聚合是数组或类 [...]

An aggregate is an array or a class [...]

和:

当聚合被初始化列表初始化时,如指定在 8.5.4 中,初始化列表的元素被视为聚合成员的初始值设定项,下标递增或会员订单.每个成员都从相应的初始化子句 [...]

When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. Each member is copy-initialized from the corresponding initializer-clause [...]

尽管初始化聚合的每个成员的副作用应该在下一个之前排序似乎是合理的,因为初始化列表中的每个元素都是一个完整的表达式.该标准实际上并不保证这一点,我们可以从 缺陷报告 1343 说:

Although it seems reasonable that side effects from initializing each member of the aggregate should be sequenced before the next, since each element in the initializer list is a full expression. The standard does not actually guarantee this we can see this from defect report 1343 which says:

当前的措辞并不表示非类对象的初始化是一个完整的表达式,但大概应该这样做.

The current wording does not indicate that initialization of a non-class object is a full-expression, but presumably should do so.

还有注意事项:

聚合初始化也可能涉及多个完整表达式,因此上面对非类对象的初始化"的限制是不正确的.

Aggregate initialization could also involve more than one full-expression, so the limitation above to "initialization of a non-class object" is not correct.

我们可以从相关的标准讨论主题 Richard Smith 说:

and we can see from a related std-discussion topic Richard Smith says:

[intro.execution]p10: "一个完整的表达式是一个不是另一个表达式的子表达式.[...] 如果语言结构被定义为产生一个函数的隐式调用,使用语言结构被认为是出于以下目的的表达式这个定义."

[intro.execution]p10: "A full-expression is an expression that is not a subexpression of another expression. [...] If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition."

因为一个花括号初始化列表不是一个表达式,在这种情况下它不会导致函数调用,5 和 s.i 是分开的全表达.然后:

Since a braced-init-list is not an expression, and in this case it does not result in a function call, 5 and s.i are separate full-expressions. Then:

[intro.execution]p14:每个值的计算和副作用与完整表达式关联的序列在每个值之前与下一个完整表达式相关的计算和副作用待评估."

[intro.execution]p14: "Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated."

所以唯一的问题是,初始化 s.i 的副作用是关联"全表达式5"的评价?我认为唯一合理的假设是:如果 5 正在初始化一个类类型的成员,构造函数调用显然是[intro.execution]p10 中定义的完整表达式,所以它很自然地假设标量类型也是如此.

So the only question is, is the side-effect of initializing s.i "associated with" the evaluation of the full-expression "5"? I think the only reasonable assumption is that it is: if 5 were initializing a member of class type, the constructor call would obviously be part of the full-expression by the definition in [intro.execution]p10, so it is natural to assume that the same is true for scalar types.

然而,我认为标准实际上并没有明确说明这一点任何地方.

However, I don't think the standard actually explicitly says this anywhere.

因此,目前标准并未对此进行指定,因此不能依赖于此,尽管如果实施未按照您期望的方式对其进行处理,我会感到惊讶.

So this is currently not specified by the standard and can not be relied upon, although I would be surprised if an implementation did not treat it the way you expect.

对于像这样的简单案例,与此类似的东西似乎是更好的选择:

For a simple case like this something similar to this seems a better alternative:

constexpr int value = 13 ;
const int foo[2] = {value, value+42};

C++17 中的变化

提案 P0507R0:核心问题 1343:非类初始化的顺序阐明了here 但没有回答完整表达式的评估中是否包含初始化的副作用的问题.所以它没有改变这是未指定的.

Changes In C++17

The proposal P0507R0: Core Issue 1343: Sequencing of non-class initialization clarifies the full-expression point brought up here but does not answer the question about whether the side-effect of initialization is included in the evaluation of the full-expression. So it does not change that this is unspecified.

这个问题的相关变化在[intro.execution]:

The relevant changes for this question are in [intro.execution]:

一个组成表达式的定义如下:

A constituent expression is defined as follows:

(9.1) — 一个表达式的组成表达式就是那个表达式.

(9.1) — The constituent expression of an expression is that expression.

(9.2) — 花括号初始化器列表或(可能带括号的)表达式列表的组成表达式是相应列表元素的组成表达式.

(9.2) — The constituent expressions of a braced-init-list or of a (possibly parenthesized) expression-list are the constituent expressions of the elements of the respective list.

(9.3) — 形式为 = initializer-clause 的大括号或等号初始化器的组成表达式是初始化子句的组成表达式.[示例:

(9.3) — The constituent expressions of a brace-or-equal-initializer of the form = initializer-clause are the constituent expressions of the initializer-clause. [ Example:

struct A { int x; };
struct B { int y; struct A a; };
B b = { 5, { 1+1 } };

用于初始化 b 的初始化器的组成表达式为 5 和 1+1.—结束示例]

The constituent expressions of the initializer used for the initialization of b are 5 and 1+1. —end example ]

[intro.execution]p12:

一个完整的表达式是

(12.1) — 一个未计算的操作数(第 8 条),

(12.1) — an unevaluated operand (Clause 8),

(12.2) — 一个常量表达式 (8.20),

(12.2) — a constant-expression (8.20),

(12.3) — 一个 init-declarator (Clause 11) 或一个 mem-initializer (15.6.2),包括初始化程序,

(12.4) — 在对象的生命周期结束时生成的析构函数的调用,而不是临时对象对象 (15.2),或

(12.4) — an invocation of a destructor generated at the end of the lifetime of an object other than a temporary object (15.2), or

(12.5) — 不是另一个表达式的子表达式并且不是其他表达式的一部分的表达式全表达.

(12.5) — an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.

所以在这种情况下 13foo[0] + 42 都是 组成表达式,它们是 full-表达.这是此处的分析 假设他们每个人都是他们自己的完整表达.

So in this case both 13 and foo[0] + 42 are constituent expression which are part of a full-expression. This is a break from the analysis here which posited that they would each be their own full-expressions.

指定初始化提案:P0329 包含以下附加内容,这似乎使这个定义很好:

The Designated Initialization proposal: P0329 contains the following addition which seems to make this well defined:

在 11.6.1 [dcl.init.aggr] 中添加一个新段落:

Add a new paragraph to 11.6.1 [dcl.init.aggr]:

聚合元素的初始化按元素顺序进行评估.那是,与给定元素相关的所有值计算和副作用按顺序排在其后的任何元素之前.

The initializations of the elements of the aggregate are evaluated in the element order. That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.

我们可以看到这反映在最新草案标准.

We can see this is reflected in the latest draft standard.

这篇关于我可以引用初始值设定项列表的先前成员吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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