我允许做一个静态,constexpr,类的初始化数据成员? [英] What am I allowed to do with a static, constexpr, in-class initialized data member?
问题描述
这可能是一个不寻常的问题,因为它要求更全面的解释给一个简短的回答另一个问题以及与之相关的C ++ 11标准的一些方面。
This is probably a bit of an unusual question, in that it asks for a fuller explanation of a short answer given to another question and of some aspects of the C++11 Standard related to it.
为了便于参考,我将在这里总结引用的问题。 OP定义了一个类:
For ease of reference, I shall sum up the referenced question here. The OP defines a class:
struct Account
{
static constexpr int period = 30;
void foo(const int &) { }
void bar() { foo(period); } //no error?
};
并且想知道为什么他没有得到关于他使用一个类初始化的静态数据成员一本书提到这是非法的)。 Johannes Schaub的回答说:
and is wondering why he gets no error about his usage of an in-class initialized static data member (a book mentioned this to be illegal). Johannes Schaub's answer states, that:
- 这违反了单一定义规则;
- 不需要诊断。
尽管我依赖这个答案的来源和有效性,我真的不喜欢它我个人觉得它太神秘了,所以我试着自己做一个更有意义的回答,只有部分成功。相关似乎是§9.4.2 / 4:
As much as I rely the source and validity of this answer, I honestly dislike it because I personally find it too cryptic, so I tried to work out a more meaningful answer myself, with only partial success. Relevant seems to be § 9.4.2/4:
静态数据成员只有一个定义是 odr-used (3.2); 不需诊断 [重点是我的]
"There shall be exactly one definition of a static data member that is odr-used (3.2) in a program; no diagnostic is required" [Emphases are mine]
位接近点。这是§3.2 / 2定义了一个 odr使用的变量:
Which gets me a bit closer to the point. And this is how § 3.2/2 defines an odr-used variable:
一个变量, evaluate表达式是odr使用,除非是满足出现在常量表达式(5.19)和中的要求的对象,因此左值到右值转换(4.1)是immediate apply [Emphases are mine]
"A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied" [Emphases are mine]
在OP的问题中,变量 period
出现在常量表达式中的要求,即 constexpr
变量。因此,必须在第二条件中找到原因:并立即应用左值到右值转换(4.1)。
In the OP's question, variable period
clearly satisfies the requirements for appearing in a constant expression, being a constexpr
variable. So the reason must be certainly found in the second condition: "and the lvalue-to-rvalue conversion (4.1) is immediately applied".
这是我解释标准的麻烦。 此第二个条件实际意味着什么?它涵盖的情况是什么?是否意味着如果从函数返回的静态 constexpr
变量不 odr使用(因此可以是类内初始化) ?
This is where I have troubles interpreting the Standard. What does this second condition actually mean? What are the situations it covers? Does it mean that a static constexpr
variable is not odr-used (and therefore can be in-class initialized) if it is returned from a function?
更一般而言:允许使用静态 constexpr
变量, -class initialize it?
More generally: What are you allowed to do with a static constexpr
variable so that you can in-class initialize it?
推荐答案
这意味着一个静态constexpr变量如果是从
函数返回的,则不是odr-used(和
因此可以是类内初始化)?
Does it mean that a static constexpr variable is not odr-used (and therefore can be in-class initialized) if it is returned from a function?
是的。
实质上,只要将其视为值,而不是 ,那么它不是odr使用。考虑如果你粘贴在值中,代码将相同地运行 - 这是当它被视为右值。但是在某些情况下它不会。
Essentially, as long as you treat it as a value, rather than an object, then it is not odr-used. Consider that if you pasted in the value, the code would function identically- this is when it is treated as an rvalue. But there are some scenarios where it would not.
只有少数情况下,基元上不执行lvalue-to-rvalue转换 ,这是参考绑定,& obj
,可能是一对夫妇,但它是很少。记住,如果编译器给你一个 const int&
引用 period
,那么你必须能够地址,此外,该地址对于每个TU必须相同 。这意味着,在C ++的可怕的TU系统中,必须有一个明确的定义。
There are only a few scenarios where lvalue-to-rvalue conversion is not performed on primitives, and that's reference binding, &obj
, and probably a couple others, but it's very few. Remember that, if the compiler gives you a const int&
referring to period
, then you must be able to take it's address, and furthermore, this address must be the same for each TU. That means, in C++'s horrendous TU system, that there must be one explicit definition.
如果它不是odr使用,编译器可以在每个TU,或替换值,或任何它想要的,你不能观察到的差异。
If it is not odr-used, the compiler can make a copy in each TU, or substitute the value, or whatever it wants, and you can't observe the difference.
这篇关于我允许做一个静态,constexpr,类的初始化数据成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!