Reputation: 165
I've learned: A user defined postfix increment operator should return a const object to behave like a fundamental arithmetic type:
int i = 0;
i++ = 42; // error, i++ is pr-value
++i = 42; // ok, ++i is l-value
so for class Widget it should be declared like
const Widget operator++(int);
...
Widget w1, w2;
w1++ = w2; // error, fine, same as i++ = 42
without const, it would compile. But with this in place, it's not possible, to call
void f(Widget&&);
f(w1++); // error, invalid initialization of Widget&& from expression const Widget
what's a pitty, cause w1++ is an r-value expression and it's constness has no impact, cause it's a temporary, isn't it?
Now, how should operator++(int) be declared? Thanks for giving advice.
Upvotes: 0
Views: 65
Reputation:
A user defined postfix increment operator should return a const object to behave like a fundamental arithmetic type:
Returning const
-qualified class types is not generally recommended in C++11. As you noticed, it prevents move operations from being used. To behave like a fundamental arithmetic type, a simpler approach is disabling the =
operator on rvalues.
struct S {
S &operator=(const S &) & = default;
S &operator=(S &&) & = default;
};
S f() { return {}; }
int main() {
S s;
s = s; // okay
s = f(); // okay
f() = s; // error
}
With this, you can declare Widget operator++(int);
, reject w1++ = w2;
, but allow f(w1++);
.
Upvotes: 2
Reputation: 141638
Widget operator++(int);
is the standard definition.
Declaring functions which return by value but also return const
, the function writer is trying to restrict what the function consumer does with the function.
Personally I never do this, it's just an unnecessary constraint and causes problems exactly like you show in this example. But other people feel that it's worth the "price" of disallowing f(w1++)
in order to get a compiler diagnostic about w1++ = w2;
which is likely to be a logic error. It's a matter of opinion and coding style really.
Upvotes: 0