1

Would it be a bad practice for some class S to overload unary operator + (or maybe operator * for non-pointer-like classes) as following?

struct S { S && operator + () & noexcept { return std::move(*this); } };

The goal it to invent shorthand for std::move.

S a;
S b = +a;
// instead of
S c = std::move(a);

Say I have a project with plenty of different classes, which intensively uses move-semantics. All the classes not mimics any arithmetical counterparts.

Tomilov Anatoliy
  • 13,614
  • 8
  • 46
  • 134
  • 16
    I think it is best just to type in `std::move` - at least it is clear to everybody what is happening. Makes maintenance a lot easier. – Ed Heal Mar 16 '16 at 16:38
  • 10
    I would hate to read that. `std::move` isn't so long after all. And writing code is a lot easier than reading it. – BoBTFish Mar 16 '16 at 16:38
  • 6
    I would not do this. Its just going to add confusion to your source code(oh what is type of this variable and is it one of the types that use the `+` move operator?). If you want to shorten `std::move` then use `using std::move;` and then at least you have `move(a)` – NathanOliver Mar 16 '16 at 16:38
  • 9
    Would be extremely unfair to anyone maintaining your code, including yourself in 3 years., – SergeyA Mar 16 '16 at 16:45
  • 3
    I guess `set_value_category_to_xvalue` (http://stackoverflow.com/q/21358432/576911) is *completely* out of the question. :-) – Howard Hinnant Mar 16 '16 at 17:05
  • @HowardHinnant Maybe there is a need to introduce some new unary prefix operators to replace `std::forward` and `std::move`? Introducing rvalue-references is core language changing, but there is no corresponding (core language) operators introduced. It seems a slight oversight, isn't it? I mean somthing like built-in `operator @` =). – Tomilov Anatoliy Mar 16 '16 at 17:17
  • If it were to become an operator, it would need to be an operator that is not overloadable. `move` is purposefully not a customization point. `forward` would be difficult to replace with an operator since it *must* be used with a template parameter (and failure to do so *must* be ill-formed). There have been similar proposals around `swap` (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3746.pdf) and they have failed to gain traction. – Howard Hinnant Mar 16 '16 at 17:24
  • @HowardHinnant Why I begin to talk about operators is the fact, that when **debug** with `-O0` it became really anoying thing to *step into* `std::move` and `std::forward` for every parameter moved to/forwarded into function, e.g. in case of `f(std::move(a), std::forward< B >(b));`. – Tomilov Anatoliy Mar 16 '16 at 17:27
  • Hmm... that sounds like (yet) another good argument in favor of libc++'s use of the `__always_inline__` attribute: https://github.com/llvm-mirror/libcxx/blob/master/include/type_traits#L2154 https://github.com/llvm-mirror/libcxx/blob/master/include/__config#L215 – Howard Hinnant Mar 16 '16 at 17:32
  • `forward` operator might be an equivalent of `std::forward< decltype(x) >(x)` – Tomilov Anatoliy Mar 16 '16 at 17:32
  • 2
    What you will win in perceived "simplicity" you will pay ten thousand times over in maintenance nightmare. – Escualo Mar 16 '16 at 17:32
  • @Escualo How do you think, is it permittable for some DSEL library? Or would it be acceptable if it became common technique to overload `operator +` for the purpose described above? – Tomilov Anatoliy Mar 16 '16 at 17:35
  • Remember that code is read many more times than it is written. Hopefully it is written once and read dozens, hundreds of times. What do you think you gain by saving a few keystrokes? Do you really think the complexity of your code comes from extra ten characters you need to write here and there? – Escualo Mar 16 '16 at 17:44
  • 2
    Remember a fundamental tenet of programming: **don't try to be clever**. Stick to the basics, keep it simple, and let the sophistication stem from the well-defined interaction between simple things. – Escualo Mar 16 '16 at 17:46
  • 1
    When you have to write `std::move` all the time, then I think you have a more fundamental design problem anyway. – Christian Hackl Mar 16 '16 at 17:48
  • @HowardHinnant Just curious, is there a link to the discussion regarding `operator:=:`? I'd to know what kind of feedback there was. – Barry Mar 16 '16 at 17:49
  • @Barry: There are discussion notes on this subject, but they are not public. However this SO answer (http://stackoverflow.com/a/20843994/576911) covers that discussion in the section titled "std::swap vs swap operator". – Howard Hinnant Mar 16 '16 at 17:55
  • @HowardHinnant Thanks! The "having both exist" argument makes sense, though seems unsatisfying. Either way, not related to this discussion. – Barry Mar 16 '16 at 18:02

3 Answers3

15

It is objectively bad practice to do such a thing. std::move() is the standard provided, well-understood way of casting to an rvalue (specifically xvalue). Anybody who sees std::move(a) either knows exactly what it does - or doesn't understand move semantics anyway (and if they don't, std::move is pretty easy to Google to learn about).

Seeing +a does not have any meaning without having to look it up first. Even worse, there is an expected meaning of what unary + does for many types - which has nothing to do with move semantics! (e.g. Is a a char getting promoted to int? Is it a no-capture lambda getting converted to a function pointer?) All for just saving 10 characters? Not to mention that you'd have to implement this operator+ for every type, and you don't have to implement std::move() at all. That is a very poor trade-off.

Peter O.
  • 28,965
  • 14
  • 72
  • 87
Barry
  • 247,587
  • 26
  • 487
  • 819
9

I would argue against this for the same reason we don't #define BEGIN { in C++: future code maintainers (and this might even be you) won't understand immediately what's going on.

Remember, you write code once and read it many times. std::move is so quick to type, clear about what it's doing, and anyone who knows C++11 will know exactly what it means.

Mark B
  • 91,641
  • 10
  • 102
  • 179
  • 1
    Well, `BEGIN` doesn't even have the perceived notion of being shorthand for anything - it is **more** characters :) – SergeyA Mar 16 '16 at 16:46
8

As Scott Meyers stated in item 7 of More Effective C++:

The purpose of operator overloading is to make programs easier to read, write, and understand

+a; is less characters to type and ... that's it. You need to look it up everytime to understand it's meaning and read it is not clear at all (+ +a, ++a, - +a ?).

Use std::move as it is easy to read, write and understand.

hlscalon
  • 6,800
  • 3
  • 28
  • 39