7

Is it possible to design and how should I make overloaded operator+ for my class C to have this possible:

C&& c = c1 + c2;

but this not possible:

c1 + c2 = something;

Edit: I changed objects to small letters. c1, c2 and c are objects of class C. && is not the logical operator&&, but rather an rvalue reference.

For example writing:

double&& d = 1.0 + 2.0;

is 100% proper (new) C++ code, while

1.0 + 2.0 = 4.0;

is obviously a compiler error. I want exactly the same, but instead for double, for my class C.

Second edit: If my operator returns C or C&, I can have assignment to rvalue reference, but also assignment to c1 + c2, which is senseless. Giving const here disables it, however it disables assignment to rvalue too. At least on VC++ 2k10. So how double does this?

Xeo
  • 129,499
  • 52
  • 291
  • 397
Argbart
  • 73
  • 3
  • 3
    This doesn't make any sense! Please provide more detail. – Mohamed Nuur May 04 '11 at 22:08
  • Please explain the semantics of your code samples (the intended results). – Emile Cormier May 04 '11 at 22:14
  • Wouldn't `double&& d = 1. + 2.;` create a dangling reference? Also, can't you just return by value? – Dennis Zickefoose May 04 '11 at 22:30
  • As I said, if I return by value, then c1 + c2 = something will be possible which is not what I want. – Argbart May 04 '11 at 22:33
  • @Dennis: Binding a temporary to a local reference extends the lifetime of the temporary just as in C++98. – fredoverflow May 04 '11 at 22:35
  • And yes, it creates dangling pointer, I used this only to simplify notation, it could be moving constructor, which takes of value of temporary which will be destroyed anyway. It just shows intention of having possibility to rvalue reference to c1 + c2 (sum object). – Argbart May 04 '11 at 22:36
  • 1
    @Fred: I was unaware they had extended the rule to include r-value references, but I suppose it makes sence that they would. – Dennis Zickefoose May 04 '11 at 22:46

1 Answers1

14

Have the assignment operator be callable on lvalues only:

class C
{
    // ...

public:

    C& operator=(const C&) & = default;
};

Note the single ampersand after the closing parenthesis. It prevents assigning to rvalues.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Thanks, it would be cool. However my VC++ 2k10 does not accept ampersand here. As I assume, it should and some day it will (or his never version ;)) Is there any way to do that in current VC++ 2k10? – Argbart May 04 '11 at 22:39
  • 1
    @Argbart: No. The language features do exist to enable this, but not within Visual Studio 2010. Remember that VS's implementation of rvalue references is relatively old and is only updated if there is a breaking problem. In future versions of the Standard, you can overload member functions depending on whether or not the class is an lvalue or rvalue. – Puppy May 04 '11 at 22:45
  • @DeadMG: Wow, that's cool, I didn't know about that! Thanks also to you, I'd also like to mark your comment as an answer and give you some points, but that's apparently not possible. Anyway, FredOverflow proposal was absolutely proper even if not useful to me. I am marking this as answer. – Argbart May 04 '11 at 22:50
  • @DeadMG: one more quick question. Does creating constructor which takes C&& as argument makes any sense? Isn't that needless because of return value optimization? – Argbart May 04 '11 at 23:00
  • @Argbart: Upvoted @DeadMG's comment for you. A constructor `C(C&&);` is a move constructor and does make sense, especially if it can be more efficient than the copy constructor by "stealing" things from the argument which is about to be destroyed. – aschepler May 04 '11 at 23:05
  • @aschepler: that exactly what I'm talking about. For example let's say, that C is polynomial class and its coefficients are in array which is rather moved than copied. However I am not sure whether it isn't done by compiler optimization in plain old C++ anyway. – Argbart May 04 '11 at 23:09
  • @Argbart: That depends on how the class is used. But there are some situations where no RVO or other temporary-elimination is allowed, but a move constructor could still help. – aschepler May 04 '11 at 23:18