Can anyone explain this paragraph of the current C++0x standard draft? - c++

Can anyone explain this statement from ISO N3242 §3.2, 2nd point
An expression is potentially evaluated unless it is an unevaluated operand
(Clause 5) or a subexpression thereof. A variable or non-overloaded
function 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. this is odr-used if it appears as a potentiallyevaluated
expression
(including as the result of the implicit transformation in the body of
a
non-static member function (9.3.1)).
ISO Standard 2003 : says
An expression is potentially evaluated unless it appears where an
integral
constant expression is required (see 5.19), is the operand of the
sizeof
operator (5.3.3), or is the operand of the typeid operator and the
expression
does not designate an lvalue of polymorphic class type (5.2.8). An
object or
non-overloaded function is used if its name appears in a
potentially-evaluated
expression.
What is the actual difference in these statements?
Can any one explain this with the help of an example/program?

"unevaluated operand" replaces "is the operand of the sizeof operator (5.3.3), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8)". It has the same basic purpose, but doesn't try to list all the cases in the C++0x standard of operators whose operands aren't evaluated. decltype is a new one, for example.
"odr-used" replaces "used", I presume they figured that "used" alone might be ambiguous with other uses of the word "use" in the standard. In both cases, though, it's defining the sense of "used" which is relevant to the ODR.
So those aren't really changes, just re-wordings updated for C++0x.
This is a change:
A variable or non-overloaded function
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.
vs.
An object or non-overloaded
function is used if its name appears
in a potentially-evaluated
expression.
Suppose a is a static const int at global scope. Then in C++03 it is not used in the following statement:
char x[a];
because the context requires a constant expression. However, it is used in the following:
void foo(int); foo(a);
because the context doesn't require a constant expression.
In C++0x, a is not odr-used in either case. It's allowed to be in a constant expression, and in the function call, lvalue-rvalue conversion is immediately applied (because foo takes its parameter by value, not reference). So it qualifies for the "unless" which wasn't present in C++03.
There's also a difference in the definition of "potentially evaluated". In the first example, char x[a], a is potentially evaluated in C++03 but not in C++0x. I haven't checked whether anything else in the standard uses "potentially evaluated", that might be affected by this change. If it's only mentioned here then that part of it isn't a change, it's just that the exception has been moved from "potentially evaluated" to "used".

Related

C++ integral constant expression definition

In the current C++ standard there is the following paragraph (expr.const#5) (emphasis mine):
An integral constant expression is an expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. [ Note: Such expressions may be used as bit-field lengths, as enumerator initializers if the underlying type is not fixed ([dcl.enum]), and as alignments. — end note ]
I have two questions regarding this definition:
Does the phrase "implicitly converted to a prvalue" mean that for an expression to be considered an "integral constant expression" it must appear in a context that forces it to be implicitly converted to a prvalue?
What does "the converted expression" refer to? I know that this question is addressed in Clarification of converted constant expression definition. The answer given there is that "the converted expression" is t, after the following initialization: T t = expr;. However, I do not see how evaluating that expression (t) would match any of the rules given in [expr.const#4] (paragraph describing required conditions for an expression to be considered a core constant expression) which would make it unqualified to be a core constant expression.
Thank you.
The statement that an integral constant expression is implicitly converted to a prvalue means that the lvalue-to-rvalue conversion is applied to any expression used as an integral constant expression. In the one case where an expression might be an integral constant expression—initializing a non-local object of const-qualified integer type that might be usable in constant expressions—the initializer is a prvalue anyway, so no change of interpretation can occur.
Beyond that, both of your questions have the same answer: whatever conversions are necessary to bring the expression (as written) to a prvalue integral type must also be allowed in a core constant expression (see, for example, /4.7 just before your citation and /6 just after it). The “converted expression” comprises the conversion in the T t=e; interpretation, not just the id-expression t (which would, for instance, always be an lvalue).
I looked at clang's source code, specifically, at the function "CheckConvertedConstantExpression" inside "SemaOverload.cpp". The operations performed there are as follows:
find the required implicit conversion sequence
check to see if only conversions listed in http://eel.is/c++draft/expr.const#7 are used
perform the implicit conversion (at this step I believe a new expression is created, e.g. if the original expression is f() which is of class type A with a user-defined conversion function to int, and the context requires an int, then the new expression should be f().operator int())
check if any narrowing conversions are required
evaluate the expression generated at step 3 (which implicitly checks if it is a constant expression)
So I believe that, as stated in #Davis Herring's answer, the term "converted expression" means a new expression whose evaluation comprises both the evaluation of the original expression, as written in the program, and the evaluation of any required conversion.

C++ full-expression standard wording

In paragraph 12 of [intro.execution] in the current (C++ 17) C++ standard draft there is written:
A full-expression is:
[...]
an expression that is not a subexpression of another expression and that is not otherwise part of a full-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. [...]
The "use of the language construct" wording refers to the fact that the construct itself is to be considered an expression or the implicit calls that the construct "uses" are to be considered as expressions?
I am asking this because in the same paragraph there is this code sample:
S s1(1); // full-expression is call of S​::​S(int)
The comment would indicate that the second interpretation is correct.
However, the paragraph explicitly says that an init-declarator is a full-expression, which would indicate that the comment is wrong.
In the past (I believe even before C++03), this paragraph looked like this (taken from this defect report):
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.
[Note: certain contexts in C++ cause the evaluation of a full-expression that results from a syntactic construct other than expression (5.19 [expr.comma]). For example, in 8.6 [dcl.init] one syntax for initializer is
( expression-list )
but the resulting construct is a function call upon a constructor function with expression-list as an argument list; such a function call is a full-expression. For example, in 8.6 [dcl.init], another syntax for initializer is
= initializer-clause
but again the resulting construct might be a function call upon a constructor function with one assignment-expression as an argument; again, the function call is a full-expression. ]
This is another reason for believing that the second interpretation is the one intended.
I know that it makes no difference to the understanding of the language, but I just want to know what was the intention of the person who initially wrote that paragraph.

Why are lambda expressions not allowed in an unevaluated operands but allowed in the unevaluated portions of constant expressions?

If we look at the draft C++ standard section 5.1.2 Lambda expressions paragraph 2 says (emphasis mine going forward):
The evaluation of a lambda-expression results in a prvalue temporary (12.2). This temporary is called the closure object. A lambda-expression shall not appear in an unevaluated operand (Clause 5). [ Note: A closure object behaves like a function object (20.8).—end note ]
and section 5.19 Constant expressions paragraph 2 says:
A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered [...]
and has the following bullet:
— a lambda-expression (5.1.2);
So why are lambdas expressions not allowed in an unevaluated operand but are allowed in the unevaluated portions of constant expressions?
I can see how for unevaluated operands the type information in several cases(decltype or typeid) is not very useful since each lambda has a unique type. Although why we would want to allow them in the unevaluated context of a constant expression is not clear, perhaps to allow for SFINAE?
The core reason for the unevaluated operands exclusion is covered in C++ Standard Core Language Defect Reports and Accepted Issues #1607. Lambdas in template parameters which seeks to clarify this restriction and states the intention of the restriction in section 5.1.2 was to:
[...] avert the need to deal with them in function template signatures [...]
As the issue documents the current wording actually has a hole since constant expressions allows them in an unevaluated context. But it does not outright state the rationale for this restriction. The desire to avoid name mangling stands out and you can infer that avoiding extending SFINAE was also desired since the proposed resolution seeks to tighten the restriction even though several viable alternatives would have allowed SFINAE. The modified version of 5.1.2 paragraph 2 as follows:
A lambda-expression shall not appear in an unevaluated operand (Clause 5 [expr]), in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments [Note: The intention is to prevent lambdas from appearing in a signature —end note]. [Note: A closure object behaves like a function object (20.10 [function.objects]). —end note]
This proposal was accepted and is in N3936(see this answer for a link)
For a more explicit discussion of the rationale to avoid having lambdas as an unevaluated operand. The discussion titled Rationale for lambda-expressions not being allowed in unevaluated contexts on comp.lang.cpp.moderated Daniel Krügler lays out three reasons:
The extreme extension of possible SFINAE cases :
[...]The reason why they became excluded was due to exactly this extreme extension of sfinae cases (you were opening a Pandora box for the compiler)[...]
In many cases it is just useless since each lambda has a unique type, the hypothetical example given:
template<typename T, typename U>
void g(T, U, decltype([](T x, T y) { return x + y; }) func);
g(1, 2, [](int x, int y) { return x + y; });
The type of the lambda in the declaration and the call are different(by definition) and therefore this can not work.
Name mangling also becomes a problem since once you allow a lambda in a function signature the bodies of the lambda will have to be mangled as well. This means coming up with rules to mangle every possible statement, which would burdensome for at least some implementations.

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:
This violates the One Definition Rule;
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?
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.
You missed a part of the premise. The class definition give above is completely valid, if you also define Account::period somewhere (but without providing an initializer). See the last sentance of 9.4.2/3:
The member shall still be defined in a namespace scope if it is odr-used
(3.2) in the program and the namespace scope definition shall not
contain an initializer.
This entire discussion only applies to static constexpr data members, not to namespace-scope static variables. When static data members are constexpr (rather than simply const) you have to initialize them in the class definition. So your question should really be: What are you allowed to do with a static constexpr data member so that you don't have to provide a definition for it at namespace scope?
From the preceding, the answer is that the member must not be odr-used. And you already found relevant parts of the definition of odr-used. So you can use the member in a context where it is not potentially-evaluated - as an unevaluated operand (for example of sizeofor decltype) or a subexpression thereof. And you can use it in an expression where the lvalue-to-rvalue conversion is immediately applied.
So now we are down to What uses of a variable cause an immediate lvalue to rvalue conversion?
Part of that answer is in §5/8:
Whenever a glvalue expression appears as an operand of an operator
that expects a prvalue for that operand, the lvalue-to-rvalue (4.1),
array-to-pointer (4.2), or function-to-pointer (4.3) standard
conversions are applied to convert the expression to a prvalue.
For arithmetic types that essentially applies to all operators that apply standard arithmetic conversions. So you can use the member in various arithmetic and logical operations without needing a definition.
I can't enumerate all things, you can or can't do here, because the requirements that something be a [g]lvalue or [p]rvalue are spread across the standard. The rule of thumb is: if only the value of the variable is used, a lvalue to rvalue conversion is applied; if the variable is used as an object, it is used as lvalue.
You can't use it in contexts where an lvalue is explicitly required, for example as argument to the address-of operator or mutating operators). Direct binding of lvalue references (without conversion) is such a context.
Some more examples (without detailed standardese analysis):
You can pass it to functions, unless the function parameter is a reference to which the variable can be directly bound.
For returning it from a function: if implicit conversion to the return type involves a user-defined conversion function, the rules for passing to a function apply. Otherwise you can return it, unless the function returns an lvalue (a reference) referring directly to the variable.
The key rule for odr-used variables, the "One Definition Rule" is in 3.2/3:
Every program shall contain exactly one definition of every non-inline
function or variable that is odr-used in that program; no diagnostic
required.
The "no diagnostic required" part means that programs violating this rule cause undefined behavior, which may range from failing to compile, compiling and failing in surprising ways to compiling and acting as if everything was OK. And your compiler need not warn you about the problem.
The reason, as others have already indicated, is that many of these violations would only be detected by a linker. But optimizations may have removed references to objects, so that no cause for linkage failure remains or else linking may sometimes occur only at runtime or be defined to pick an arbitrary instance from multiple definitions of a name.

Where in the C++11 standard does it specify when a constexpr function can be evaluated during translation?

Just because a function (or constructor)...
is declared constexpr and
the function definition meets the constexpr requirements
...doesn't mean that the compiler will evaluate the constexpr function during translation. I've been looking through the C++11 FDIS (N3242, available at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/) to try and determine two things:
When is the compiler obligated to evaluate a constexpr function during translation?
When is the compiler allowed to evaluate a constexpr function during translation?
Section 5.19 Paragraph 1 says that constant expressions can be evaluated during translation. As far as I can comprehend, the remainder of Section 5.19 sets forth the rules for what is valid in the definition of a constexpr function.
I understand that I can force constexpr evaluation during translation by declaring the result of the constexpr function as constexpr. Like this:
// Declaration
constexpr double eulers_num() { return 2.718281828459045235360287471; }
// Forced evaluation during translation
constexpr double twoEulers = eulers_num() * 2.0;
static_assert(twoEulers > 5.0, "Yipes!");
So far I've been unable to find the paragraphs in the FDIS that:
Force twoEulers to be evaluated during translation or
Specify other situations when the compiler may or must evaluate a constexpr function during translation.
What I'm particularly interested in discovering is whether constexpr evaluation during translation is triggered by:
When all parameters passed to the constexpr function are literals, or
The implied object argument during overload resolution (Section 13.3.1 Paragraph 3) is either constexpr or requires a literal (such as for array dimensions), or
Something else entirely.
Please, if possible, in your responses cite sections of the FDIS that I can look up or key phrases I can search in the FDIS. The English in the standard is somewhat obtuse, so I may have been reading the relevant paragraphs and have entirely missed their meaning or intent.
It is "allowed" to evaluate the constexpr call at compile time whenever it is actually possible to do so. Remember that the specification operates under the "as if" rule. So if you can't tell the difference, the compiler can do whatever it wants.
The compiler is required to evaluate constexpr calls at compile time when it actually needs the answer at compile time. For example:
constexpr int foo() {return 5;}
std::array<float, foo()> arr;
The compiler needs to know the array size at compile time. Therefore, it must evaluate the constant expression at compile time. If the constexpr function cannot be executed at compile time, you get a compile-time error.
Nicol Bolas is 100% correct, but there is one other interesting aspect: whether the expression is evaluated at translation-time and whether it is evaluated at run-time are completely independent questions. Since the constant expression cannot have side-effects, it can be evaluated an arbitrary number of times, and nothing stops it from being evaluated at both translation-time and run-time.
Suppose the constant expression were a large array (not a std::array, just an array), which is entirely legal, and the program does not indicate that it has static storage. Suppose also that only element 7 of the array is used in a context in which compile-time computation is necessary. It is quite reasonable for the compiler to compute the entire array, use element 7, discard it, and insert code to compute it at run-time in the scope in which it is used, rather than bloating the binary with the whole computed array. I believe this is not a theoretical issue; I've observed it with various compilers in various contexts. constexpr does not imply static.
Of course, if the compiler can determine that the array is not used at runtime, it might not even insert code to compute it, but that's yet another issue.
If you do use such an object at run-time, and you want to indicate to the compiler that it would be worth keeping it around for the duration of the program, you should declare it as static.
By combing the FDIS I have found three places that specify where a constexpr expression must be evaluated during translation.
Section 3.6.2 Initialization of non-local variables, paragraph 2 says if an object with static or thread local storage duration is initialized with a constexpr constructor then the constructor is evaluated during translation:
Constant initialization is performed:
if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers is a constant expression;
Section 7.1.5 The constexpr specifier, paragraph 9 says if an object declaration includes the constexpr specifier, that object is evaluated during translation (i.e., is a literal):
A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.19). Otherwise, every full-expression that appears in its initializer shall be a constant expression. Each implicit conversion used in converting the initializer expressions and each constructor call used for the initialization shall be one of those allowed in a constant expression (5.19).
I’ve heard people argue that this paragraph leaves room for an implementation to postpone the initialization until runtime unless the effect can be detected during translation due to, say, a static_assert. That is probably not an accurate view because whether a value is initialized during translation is, under some circumstances, observable. This view is reinforced by Section 5.19 Constant expressions paragraph 4:
[ Note: Although in some contexts constant expressions must be evaluated during program translation, others may be evaluated during program execution. Since this International Standard imposes no restrictions on the accuracy of floating-point operations, it is unspecified whether the evaluation of a floating-point expression during translation yields the same result as the evaluation of the same expression (or the same operations on the same values) during program execution... — end note ]
Section 9.4.2 Static data members, paragraph 3 says if a const static data member of literal type is initialized by a constexpr function or constructor, then that function or constructor must be evaluated during translation:
If a static data member is of const literal type, its declaration in the class definition can specify a brace-orequal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ]
Interestingly, I did not find anything in the FDIS that required a constexpr expression to be evaluated if its result is used as an array dimension. I'm quite sure the standard committee expects that to be the case. But I also could have missed that in my search.
Outside of those circumstances the C++11 standard allows computations in constexpr functions and constructors to be performed during translation. But it does not require it. The computations could occur at runtime. Which computations the compiler performs during translation are, to a certain extent, a quality of implementation question.
In all three of the situations I located, the trigger for translation-time evaluation is based on the requirements of the target using the result of the constexpr call. Whether or not the arguments to the constexpr function are literal is never considered (although it is a pre-requisite for valid evaluation).
So, to get to the real point of this, it appears that constexpr evaluation during translation is triggered by:
The implied object argument during overload resolution (Section 13.3.1 Paragraph 3) is either constexpr or requires a literal.
I hope that's helpful to someone besides me. Thanks to everyone who contributed.
I don't think it's forced anywhere. I had a look too, it's tricky because there's not one paper on constexpr in that list; they all seem to add/remove from the previous collection of papers.
I think the general idea is when the inputs to the constexpr function are constexpr themselves, it'll all be done at compile time; and by extension non-function constexpr statements, which are literal anyway will be run at compile time if you're using a half intelligent compiler.
If a constexpr function or constructor is called with arguments which
aren't constant expressions, the call behaves as if the function were
not constexpr, and the resulting value is not a constant expression.
from wikipedia
which in seem to get the info from this pdf:
constexpr functions: A constexpr function is one which is “suf-
ficiently simple” so that it delivers a constant expression when
called with arguments that are constant values (see §2.1).