Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contradiction on result objects of prvalues #2300

Closed
geryogam opened this issue Aug 16, 2018 · 2 comments
Closed

Contradiction on result objects of prvalues #2300

geryogam opened this issue Aug 16, 2018 · 2 comments
Assignees

Comments

@geryogam
Copy link
Contributor

geryogam commented Aug 16, 2018

I find this part of the C++ standard draft conflicting, section [basic.lval], § 5:

The result object of a prvalue is the object initialized by the prvalue; a prvalue that is used to compute the value of an operand of an operator or that has type cv void has no result object. [Note: Except when the prvalue is the operand of a decltype-specifier, a prvalue of class or array type always has a result object. For a discarded prvalue, a temporary object is materialized; see 7.2. —end note]

What about a prvalue of class or array type being used as the operand of an operator? The normative sentence of the paragraph seems to state that it will have no result object. But the note states the opposite. So there is a conflict, unless a class or array prvalue cannot be the operand of an operator (except of a decltype-specifier).

Section [basic.lval], § 7:

Whenever a prvalue appears as an operand of an operator that expects a glvalue for that operand, the temporary materialization conversion (7.3.4) is applied to convert the expression to an xvalue.

and section [class.temporary], § 2:

[ Note: Temporary objects are materialized:

  • when binding a reference to a prvalue ([dcl.init.ref], [expr.type.conv], [expr.dynamic.cast], [expr.static.cast], [expr.const.cast], [expr.cast]),
  • when performing member access on a class prvalue ([expr.ref], [expr.mptr.oper]),
  • when performing an array-to-pointer conversion or subscripting on an array prvalue ([conv.array], [expr.sub]),
  • when initializing an object of type std​::​initializer_­list from a braced-init-list ([dcl.init.list]),
  • for certain unevaluated operands ([expr.typeid], [expr.sizeof]), and
  • when a prvalue appears as a discarded-value expression ([expr.prop]).
    — end note ]

seem to head in that direction by stating that a class or array prvalue can never be an operand of a built-in operator because of prvalue-to-xlvalue conversion. But this is not true for an overloaded operator, as it can directly take a prvalue operand (no prior prvalue-to-xlvalue conversion thanks to guaranteed copy elision):

struct A {
  A operator+(A);
};

A a = A() + A();

So shouldn’t the part be reformulated as following? (This has been suggested to me by Richard Smith.)

The result object of a prvalue is the object initialized by the prvalue; a prvalue that is used to compute the value of an operand of a built-in operator or that has type cv void has no result object. [Note: Except when the prvalue is the operand of a decltype-specifier, a prvalue of class or array type always has a result object. For a discarded prvalue, a temporary object is materialized; see 7.2. —end note]

@languagelawyer
Copy link
Contributor

a class or array prvalue cannot be the operand of the built-in operators

AFAIR, a class prvalue can be an operand of the conditional operator.

@geryogam
Copy link
Contributor Author

geryogam commented Aug 19, 2018

@languagelawyer

AFAIR, a class prvalue can be an operand of the conditional operator.

You are right, and also the built-in comma operator accept prvalue operands of class or array type:

struct C {};
using A = int[3];
true ? C{} : C{};  // class prvalue operands of the built-in conditional operator
C{}, C{};          // class prvalue operands of the built-in comma operator
A{}, A{};          // array prvalue operands of the built-in comma operator

Thus I should have rather said:

a class or array prvalue can never be an operand of a built-in operator because of prvalue-to-xlvalue conversion, except for the built-in conditional and comma operators for which no conversion occur.

But since in these cases no prvalue-to-xlvalue conversion occur, no temporary object is materialized. Therefore there is still no result object. So the above suggestion of changing section [basic.lval], § 5 of the C++ standard draft to restrict the absence of result objects to only all built-in operators still holds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants