[ACCEPTED]-Macros to disallow class copy and assignment. Google -vs- Qt-c++

Accepted answer
Score: 50

It doesn't matter. The return type is not 8 part of a function's signature, as it does 7 not participate in overload resolution. So 6 when you attempt to perform an assignment, both 5 declarations will match, regardless of whether 4 you use the return type.

And since the entire 3 point in these macros is that the functions 2 will never get called, it doesn't matter 1 that one returns void.

Score: 16

I'd just like to mention that there is an 9 alternative strategy for implementing an 8 abstraction for disallowing copy and assignment 7 of a class. The idea is to use inheritance 6 instead of the preprocessor. I personally 5 prefer this approach as I follow the rule 4 of thumb that it is best to avoid using 3 the preprocessor when at all possible.

boost::noncopyable is 2 an example implementation. It is used as 1 follows:

class A : noncopyable
Score: 10

See Boost.Utility, specifically boost::noncopyable. It's not 15 a macro but a base class with private copy 14 and assignment. It prevents the compiler 13 from generating implicit copy and assignment 12 in derived classes.

edit: Sorry, this was 11 not an answer to the original question. By 10 the way, boost::noncopyable uses a const 9 reference as return type for the assignment 8 operator. I was under the impression that 7 the type of the return value doesn't matter 6 since it's not supposed to be used. Still, making 5 the operator private doesn't prevent usage 4 inside the class or friends in which case 3 a non-usual return type (like void, a const 2 reference, etc) might lead to compilation 1 errors and catch additional bugs.

Score: 5

There's no practical difference. The assignment 8 operator signatures differ just as a matter 7 of style. It's usual to have an assignment 6 operator returning a reference to allow 5 chaining:

a = b = c;

but a version returning 4 void is also legal and will work just fine for 3 cases when the only purpose is to just declare 2 the operator private and therefore prohibited to 1 use.

Score: 4

From the standard, 12.8, clause 9: "A user-declared 22 copy assignment operator X::operator= is a non-static 21 non-template member function of class X with 20 exactly one parameter of type X, X&, const 19 X&, volatile X&, or const volatile X&." It says 18 nothing about the return type, so any return 17 type is permissible.

Clause 10 says "If the 16 class definition does not explicitly declare 15 a copy assignment operator, one is declared 14 implicitly."

Therefore, declaring any X::operator=(const X&) (or 13 any other of the specified assignment types) is 12 sufficient. Neither the body nor the return 11 type is significant if the operator will 10 never be used.

Therefore, it's a stylistic 9 difference, with one macro doing what we'd 8 likely expect and one saving a few characters 7 and doing the job in a way that's likely 6 to surprise some people. I think the Qt 5 macro is better stylistically. Since we're 4 talking macro, we're not talking about the 3 programmer having to type anything extra, and 2 failing to surprise people is a good thing 1 in a language construct.

Score: 2

Others have already answered why it's legal 9 to have different return values for operator=; IMHO 8 jalf said it best.

However, you might wonder why Google 7 uses a different return type, and I suspect 6 it's this:

You don't have to repeat the type 5 name when disabling the assignment operator 4 like this. Usually the type name is the 3 longest part of the declaration.

Of course, this 2 reason is void given that a macro is used 1 but still - old habits die hard. :-)

Score: 1

Both serve the same purpose

Once you write 4 this one:

Class &operator=(const Class &);

you will get the benefits of chain 3 assignments. But in this case you want the 2 assignment operator to be private. so it 1 doesn't matter.

Score: 1

Qt version is backward compatible, while 8 google's is not.

If you develop your library 7 and deprecate the use of assignment before 6 you completely remove it, in Qt it will 5 most likely retain the signature it originally 4 had. In this case older application will 3 continue to run with new version of library 2 (however, they won't compile with the newer version).

Google's 1 macro doesn't have such a property.

Score: 1

As several other answers have mentioned, the 18 return type of the function doesn't participate 17 in the function signature, so both declarations 16 are equivalent as far as making the assignment 15 operator unusable by clients of the class.

Personally 14 I prefer the idiom of having a class privately 13 inherit from an empty non-copyable base 12 class (like boost::noncopyable, but I have 11 my own so I can use it in projects that 10 don't have boost available). The empty 9 base class optimization takes care of making 8 sure there's zero overhead, and it's simple, readable, and 7 doesn't rely on the dreaded preprocessor 6 macro functionality.

It also has the advantage 5 that copy and assignment can't even be used 4 within class implementation code - it'll 3 fail at compile time while these macros 2 will fail at link time (likely with a less 1 informative error message).

Score: 0

Incidentally, if you have access to the 3 Boost libraries (You don't? Why the heck 2 not??), The Utility library has had the 1 noncopyable class for a long time:

class YourNonCopyableClass : boost::noncopyable {

Clearer IMHO.

Score: 0

In practice I would say that both should 9 not be used anymore if you have a C++11 8 compiler.

You should instead use the delete 7 feature , see here

Meaning of = delete after function declaration

and here


Why : essentially 6 because compiler message is much more clearer. When 5 the compiler need one of the copy or copy 4 assignment operator, it immediately points 3 out to the line where the =delete was coded.

Better 2 and complete explanations can also be found 1 in Item 11: Prefer deleted functions to private undefined ones from Effective Modern C++ book by Scott Meyers

More Related questions