11

Is there a reason to use the “canonical” signatures for operator=

class X { X& operator=(const X&) = delete; X& operator=(X&&) = delete; }; 

instead of just

class X { void operator=(X) = delete; }; 

when all you want to do is delete it?

Upd:
Also, consider a situation when X has an explicitly declared move or copy constructor.

class X { public: X(X&&); }; 

In that case op=(X&&) and op=(const X&) are implicitly deleted, but I want to explicitly express that assignment is not allowed.

12
  • 2
    Why do you need to delete both the copy and move assignment operators in the first example? X& operator=(const X&) = delete; alone should be enough, no? A move assignment operator will not be implicitly declared due to the presence of your user declared copy assignment operator. Commented Dec 9, 2015 at 18:31
  • 4
    As a guideline, never delete the special move members. If you do so, the best you can hope for is that you've created redundant noise. At worst, it won't do what you were hoping for. X& operator=(const X&) = delete; is sufficient, and succinct. Commented Dec 9, 2015 at 18:53
  • 2
    @DietmarKühl: Yes, identical in functionality. Not more succinct though (both one liners). And questionable on readability because the X& operator=(const X&) = delete; is more common/familiar and so your reader has to stop and figure out why the unusual signature. Ultimately this boils down to a style issue, and I'm recommending X& operator=(const X&) = delete;. Commented Dec 9, 2015 at 19:26
  • 2
    Tape this above your monitor until you have it memorized: stackoverflow.com/a/24512883/576911 :-) Commented Dec 9, 2015 at 19:29
  • 1
    And unit test all 6 special member whether you have them or not like this: github.com/HowardHinnant/date/blob/master/test/date_test/… Commented Dec 9, 2015 at 19:31

1 Answer 1

6

No, there is no technical reason to use the canonical copy assignment operator signature.

As seen in the standard, [dcl.fct.def.delete] §8.4.3:

  1. A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. — end note ]

Therefore a deleted function's name, in this case operator=, may only be used if the compiler finds a preferable overload resolution. However, such an overload cannot exist, as X and const X& are indistinguishable as parameters ([over.ics.rank] §13.3.3.2) and the return value is ignored.

That being said, there is a stylistic reason to use the canonical signature. The mere fact that this question exists shows that anyone reading your code may not know the meaning and assume it is doing something special. For readability's sake, I would recommend you use the familiar X& operator=(const X&) = delete;.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.