Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
563 views
in Technique[技术] by (71.8m points)

c++ - What am I allowed to do with a static, constexpr, in-class initialized data member?

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.

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

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:

  1. This violates the One Definition Rule;
  2. No diagnostics is required.

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:

"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]

Which gets me a bit closer to the point. And this is how § 3.2/2 defines an odr-used variable:

"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]

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".

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?

More generally: What are you allowed to do with a static constexpr variable so that you can in-class initialize it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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?

Yes.

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.

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.

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...