1

cppreference is said that: any expression that designates a temporary object after temporary materialization is xvalue expression (since C++17).

Temporary materialization is:

A prvalue of any complete type T can be converted to an xvalue of the same type T. This conversion initializes a temporary object of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object.

What I suspect that I am not understood is that, from this quote, the temporary materialization conversion (prvalue->xvalue) produces an xvalue denoting to the temporary object. To clear what I am not fully understanding, I will provided a simple example:

const T& t = T(); 

The reference t is bound to prvalue T(). So a temporary of type T gets created and initialized from this prvalue; then the reference will bind to that temporary. I think the temporary looks like this: and t reference will bind to it:

T __tmp{ };
const T& t = __tmp; 

Indeed the above two lines are happened implicitly, but in general, can I said that the expression __tmp in the assignment const T& t = __tmp; is xvalue expression?

Till now I am assuming I was true, if not, what does cppreference mean by "any expression that designates a temporary object, after temporary materialization is xvalue expression"? where's exactly the xvalue expression now? what does the word "designates" means in this context?

  • 3
    What version of C++ do you want an answer for? Starting in C++17 `T t = T(1);` is mandated to be elided to `T t(1);` so no xvalue. – NathanOliver Mar 08 '22 at 15:46
  • @NathanOliver - good point. I meant before C++17. Edit the question if you can. –  Mar 08 '22 at 15:51
  • I added the C++14 tag as that version is not required to elide the xvalue away, its just an option the compiler can take as long as it follows specific rules. – NathanOliver Mar 08 '22 at 15:55
  • 1
    @NathanOliver, I think the compiler need `-fno-elide-constructors` to disable the optimization? Or it's irrelvalent? –  Mar 08 '22 at 15:57
  • 1
    You needed `-fno-elide-constructors` in C++14 and earlier to disable the elision if the compiler was doing so, but in C++17, the compiler is required to do the elision so the flag wont stop it. – NathanOliver Mar 08 '22 at 16:02
  • 1
    @NathanOliver - the elision is enabled as long as the argument `-fno-elide-constructors` is not set regardless of the standard version being used. – mada Mar 08 '22 at 16:11
  • 7
    @cpper: The concept of "temporary materialization" does not exist in C++14. It was added to C++17. In C++14, a prvalue *is a temporary*; nothing "materializes". So you need to edit your question to make it more coherent. If you want a C++14 answer, you need to cite text talking about how C++14 behaves. – Nicol Bolas Mar 08 '22 at 16:23
  • @0x0 It's only allowed in specific cases though. Before C++17, even if the compiler wanted to elide the temporary it couldn't if the object didn't have an accessible copy or move constructor. In C++17, that no longer mattered and a prvalue could be elided even for types that cannot be moved or copied. – NathanOliver Mar 08 '22 at 16:31
  • @NicolBolas - When you comment opposed on a question here, you are actually making people think that the question is wrong and has no answer. As possible as I can I will edit the question to be specific. The quote I cited from cppreference is actually since C++17 not until C++17. –  Mar 09 '22 at 13:44
  • @cpper: "*you are actually making people think that the question is wrong and has no answer*" That's because your question was wrong and had no answer as you stated it. At the time, your question was tagged C++14. And from the comments, that tag was added *precisely because* you said, "I meant before C++17." If that was a typo and you meant "after", OK, but it isn't my fault that your mistake made the question unanswerable. – Nicol Bolas Mar 09 '22 at 14:15
  • @NicolBolas - I am very sorry since my question is not consistent. But does the question now is answerable ? or need any edit? –  Mar 09 '22 at 14:34

2 Answers2

1

When the compiler converts const T& t = T(); into the AST, it looks roughly like this:

`-DeclarationStatement
  `-VariableDeclaration (name: t, type: const T&)
    `-InitializerExpr (type: const T, category: glvalue)
      `-MaterializeTemporaryExpr (type: const T, category: xvalue) [conv.rval]
        `-ImplicitCastExpr (type: const T, category: prvalue) [dcl.init.ref#5.3]
          `-ExplicitCastExpr (type: T, category: prvalue) [expr.type.conv]

(the ImplicitCastExpr is from the words "adjusted to" in dcl.init.ref#5.3.sentence-2)

so to answer

where's exactly the xvalue expression now?

it's the MaterializeTemporaryExpr on the syntax tree. There are many such implicit conversions in C++ (and even in C, e.g. consider the AST of 1.2/2

can I said that the expression __tmp in the assignment const T& t = __tmp; is xvalue expression

no; that's lvalue per expr.prim.id and so it takes a very different path through [dcl.init.ref]. Also there is no assignment

Cubbi
  • 46,567
  • 13
  • 103
  • 169
0

can I said that the expression __tmp in the assignment const T& t = __tmp; is xvalue expression?

It would be better to say that the code you showed as equivalent is incorrect because it doesn't include the xvalue conversion step. A more accurate version would be:

T __tmp{ };
const T& t = std::move(__tmp);

The std::move cast results in an xvalue expression referring to the object __tmp.

what does the word "designates" means in this context?

The same thing it means in other contexts. It isn't being used as a special term. It's just the word "designate": to mark or point out; indicate; show; specify. The expression T() indicates/shows/specifies a particular object.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 1
    And for a more complex example, the expression `std::find(v.begin(), v.end(), 42)` also "designates" a prvalue (an iterator value). – j6t Mar 09 '22 at 15:26