1

Suppose I have the following:

class foo
{
public:
    foo& Ref() { return *this; }

    int stuff;
};

void do_stuff(foo& f)
{
    f.stuff = 1;
}

int main()
{
    do_stuff(foo().Ref());
}

I'm modifying an rvalue via lvalue reference. Is this legal? If so or if not, can someone explain why and provide relevant section in the standard?

void.pointer
  • 24,859
  • 31
  • 132
  • 243

1 Answers1

6

I'm modifying an rvalue via lvalue reference.

No you're not. Inside do_stuff, the expression f is an lvalue, not an rvalue. Value categories are about expressions, not objects; objects have types.

You're modifying a temporary, but that's fine. There is no simple single paragraph I can quote that says this; it's simply not prohibited anywhere to modify an object that happens to be a temporary.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • The temporary is an rvalue though. I'm not modifying the reference itself. – void.pointer Nov 11 '14 at 21:46
  • 1
    @void.pointer: No it's not. There is no such thing as "this object is an lvalue", "this object is an rvalue". That's not how value categories work. Value categories are a property of _expressions_, for example the expression `f` which happens to name an object that you've declared (and is thus, in this example, an _lvalue_ expression). – Lightness Races in Orbit Nov 11 '14 at 21:46
  • yes it is??? Please explain instead of saying "no its not". By the time I actually *use* `f`, yes it's an lvalue, but I'm thinking of this problem in terms of its origin (where the memory is located, sort of). Anyway, this seems like a distraction from what I'm ultimately trying to ask. – void.pointer Nov 11 '14 at 21:47
  • @void.pointer: I feel like you're consistently reading only about 5% of my words. Please examine my answer and comments again. This isn't a "distraction"; it's the answer to your question, which is fundamentally flawed for the reasons given. – Lightness Races in Orbit Nov 11 '14 at 21:48
  • Please stop editing your comments/answer every 5 seconds and maybe I can read everything. – void.pointer Nov 11 '14 at 21:48
  • @void.pointer: Okay you're just being rude and obnoxious now. I'm not answering again. – Lightness Races in Orbit Nov 11 '14 at 21:48
  • 2
    @void.pointer Maybe this will clear things up: temporaries are not allowed to bind to non-const references *directly*, but this is to prevent programmer mistakes and not because the temporary is immutable. The temporary object is guaranteed to exist until the end of the *full-expression* in which it appears, so references to the object for the duration of the *full-expression* are valid. – cdhowie Nov 11 '14 at 21:54
  • @cdhowie Thanks, that clears things up. And I wasn't trying to be rude, we were just both typing comments at the same time and due to refresh issues I didn't see everything you were saying (so yes I was only reading 5%). Also my use of language was incorrect, I meant temporary through lvalue as you mentioned, apologies for the confusion. – void.pointer Nov 11 '14 at 21:58
  • @void.pointer And lightning is correct; the object itself isn't an lvalue or an rvalue. The expression `foo()` is an rvalue but that doesn't mean that the *value of that expression* can't be referred to by a different expression that is an lvalue, as happens in multiple places (`*this` and the `f` argument, in particular). – cdhowie Nov 11 '14 at 21:58