I am rereading Scott Meyers’ Effective C++ after a hiatus of 16 years. Although I have not read the latest C++ standard, but it has come to my attention that C++ has changed since the second edition of Effective C++ was written.
In the third edition of his book, Scott Meyers has mentioned that even if you have an empty class, meaning there is nothing to initialize or assign, a C++ compiler will still generate at least 3 default functions, namely, default constructor, default copy constructor, assignment operator, and probably some other functions. According to Mr. Meyers, the following code will result in the generation of the aforementioned functions.
class Empty {}
Empty E1; // Default constructor.
Empty E2 ( E1 ); // Default copy constructor.
E1 = E2; // Default assignment operator.
Considering that there really is nothing to initialize, as the class is empty, does the C++ still generate some sort of code for the stated functions?
probably some other functions.
Yes, the move constructor and the move assignment operator. That's it.
Considering that there really is nothing to initialize, as the class is empty, does the C++ still generate some sort of code for the stated functions?
Sometimes. What happens is that those special members are declared, but not defined. They are only defined when they are used (i.e. odr-used or constant evaluated), otherwise, there is no code generated for them as they aren't defined.
And because you have an empty class, if the special members are defined, they will do nothing at all.
I would like to use libtooling to test whether the defined by a CXXRecordDecl is copy constructable.
I have already tried :
hasCopyConstructorWithConstParam()
hasTrivialCopyConstructor() || hasNonTrivialCopyConstructor()
Unfortunately, both of those expressions return true if the class's copy constructor is implicitly deleted. This can occur if the class inherits from a non-copyable class or has a member variable that is non-copyable.
The logic to test whether a class is copy constructable is non-trivial and must be exist somewhere in clang. How can I test if a class is copy constructable with libtooling?
Turn comment into answer:
You can retrieve the constructor with CXXRecordDecl::ctor_begin
and check CXXConstructorDecl::isDeleted().
Is there a way to actually see (output to file, console etc) implicit compiler generated or = default methods (in C++)?
(Target compilers: vc, clang, gcc)
I'd like to see how these functions are actually implemented. For example, how does the assignment operator assigns its values, does it check for self assignment, is const correctness given etc). I did not found any statisfying result on the www that actually shows the implementations of these compiler generated functions.
The semantics of the "special member" functions are defined by the C++ standard, in
section 12
In brief, they do what you think they do;
The default will invoke the defaults of the bases and the members
The copy will invoke the copy of the bases and members
The same applies for the moves, assignments and destructor
If, for some reason, one of them would violate a const correctness or the corresponding constructor or assignment of the base or members is not available, or some other issue arrises, then that special member is not declared.
An an additional note; there are specific rules that apply to the defaults if one (or some) of the special members are defined by the user (detailed here).
When declaring a class/struct/union the compiler will generate the default methods (rule of three). This also will happen when = default'ing these methods.
How do the default methods exactly look like?
For each of these methods, the compiler defines default inline methods that call the default methods of each attribute of the object. (so a pointer won't be initialized neither any built-in type).
For example let consider the default constructor. According to the C++ Standard
An implicitly-declared default constructor is an inline public member
of its class.
and
The implicitly-defined default constructor performs the set of
initializations of the class that would be performed by a user-written
default constructor for that class with no ctor-initializer (12.6.2)
and an empty compound-statement.
So it looks like
struct A
{
A() {}
};
except that it is not explicitly declared and defined.
About copy constructor you can read at my personal forum
http://cpp.forum24.ru/?1-1-0-00000021-000-0-0-1388485669
Though it is written in Russian but you can translate it for example using google service translate.
Those method will do the minimum necessary to initialize the class.
Default construtor - do nothing with simple members but call the constructors of more complex members (class/struct) as well as call the ctor of its super class.
Copy constructor will perform a shallow copy (memcpy).
To disallow copying or assigning a class it's common practice to make the copy constructor
and assignment operator private. Both Google and Qt have macros to make this easy and visible.
These macros are:
Google:
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
Qt:
#define Q_DISABLE_COPY(Class) \
Class(const Class &); \
Class &operator=(const Class &);
Questions:
Why are the signatures of the two assignment operators different? It seems like the Qt version is correct.
What is the practical difference between the two?
It doesn't matter. The return type is not part of a function's signature, as it does not participate in overload resolution. So when you attempt to perform an assignment, both declarations will match, regardless of whether you use the return type.
And since the entire point in these macros is that the functions will never get called, it doesn't matter that one returns void.
I'd just like to mention that there is an alternative strategy for implementing an abstraction for disallowing copy and assignment of a class. The idea is to use inheritance instead of the preprocessor. I personally prefer this approach as I follow the rule of thumb that it is best to avoid using the preprocessor when at all possible.
boost::noncopyable is an example implementation. It is used as follows:
class A : noncopyable
{
...
};
See Boost.Utility, specifically boost::noncopyable. It's not a macro but a base class with private copy and assignment. It prevents the compiler from generating implicit copy and assignment in derived classes.
edit: Sorry, this was not an answer to the original question. By the way, boost::noncopyable uses a const reference as return type for the assignment operator. I was under the impression that the type of the return value doesn't matter since it's not supposed to be used. Still, making the operator private doesn't prevent usage inside the class or friends in which case a non-usual return type (like void, a const reference, etc) might lead to compilation errors and catch additional bugs.
There's no practical difference. The assignment operator signatures differ just as a matter of style. It's usual to have an assignment operator returning a reference to allow chaining:
a = b = c;
but a version returning void is also legal and will work just fine for cases when the only purpose is to just declare the operator private and therefore prohibited to use.
From the standard, 12.8, clause 9: "A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X&, or const volatile X&." It says nothing about the return type, so any return type is permissible.
Clause 10 says "If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly."
Therefore, declaring any X::operator=(const X&) (or any other of the specified assignment types) is sufficient. Neither the body nor the return type is significant if the operator will never be used.
Therefore, it's a stylistic difference, with one macro doing what we'd likely expect and one saving a few characters and doing the job in a way that's likely to surprise some people. I think the Qt macro is better stylistically. Since we're talking macro, we're not talking about the programmer having to type anything extra, and failing to surprise people is a good thing in a language construct.
Others have already answered why it's legal to have different return values for operator=; IMHO jalf said it best.
However, you might wonder why Google uses a different return type, and I suspect it's this:
You don't have to repeat the type name when disabling the assignment operator like this. Usually the type name is the longest part of the declaration.
Of course, this reason is void given that a macro is used but still - old habits die hard. :-)
Both serve the same purpose
Once you write this one:
Class &operator=(const Class &);
you will get the benefits of chain assignments. But in this case you want the assignment operator to be private. so it doesn't matter.
Qt version is backward compatible, while google's is not.
If you develop your library and deprecate the use of assignment before you completely remove it, in Qt it will most likely retain the signature it originally had. In this case older application will continue to run with new version of library (however, they won't compile with the newer version).
Google's macro doesn't have such a property.
As several other answers have mentioned, the return type of the function doesn't participate in the function signature, so both declarations are equivalent as far as making the assignment operator unusable by clients of the class.
Personally I prefer the idiom of having a class privately inherit from an empty non-copyable base class (like boost::noncopyable, but I have my own so I can use it in projects that don't have boost available). The empty base class optimization takes care of making sure there's zero overhead, and it's simple, readable, and doesn't rely on the dreaded preprocessor macro functionality.
It also has the advantage that copy and assignment can't even be used within class implementation code - it'll fail at compile time while these macros will fail at link time (likely with a less informative error message).
Incidentally, if you have access to the Boost libraries (You don't? Why the heck not??), The Utility library has had the noncopyable class for a long time:
class YourNonCopyableClass : boost::noncopyable {
Clearer IMHO.
In practice I would say that both should not be used anymore if you have a C++11 compiler.
You should instead use the delete feature , see here
Meaning of = delete after function declaration
and here
http://www.stroustrup.com/C++11FAQ.html#default
Why : essentially because compiler message is much more clearer. When the compiler need one of the copy or copy assignment operator, it immediately points out to the line where the =delete was coded.
Better and complete explanations can also be found in Item 11: Prefer deleted functions to private undefined ones from Effective Modern C++ book by Scott Meyers