In §12 of the standard every special member function has a set of rules which cause it to be implicitly declared as defaulted and another set of rules which cause a defaulted [special member function to be] defined as deleted.
This makes it seem (to me) that there are 3 potential states when no user-declared version is present for special member functions: declared and defined (defaulted), declared and undefined (deleted), and undeclared. Is this accurate? If so, what point is there as opposed to cutting out the 'undeclared' option?
* declared as defaulted seems like a mistake, shouldn't it be "defined" as defaulted?
The difference between a deleted constructor and an implicitly undeclared constructor is that the deleted constructor participates in overload resolution, whereas the constructor that doesn't exist, doesn't participate in overload resolution.
Example:
This class is default constructible. The compiler does not implicitly declare a defaulted constructor for it.
struct A
{
template <class ...T>
A(T...) {}
};
int main()
{
A a; // ok
}
If the compiler did declare a default constructor for it, and if that default constructor was defined as deleted, then A would not be default constructible. That can be simulated with:
struct A
{
A() = delete; // pretend the compiler implicitly declared and defined this
template <class ...T>
A(T...) {}
};
int main()
{
A a;
}
error: call to deleted constructor of 'A'
A a;
^
Similar problems appear with the move constructor. If the compiler decides to implicitly declare it and define it as deleted, then one can not construct such a class from an rvalue, even if it has a viable copy constructor:
#include <type_traits>
struct A
{
A();
A(const A&);
A(A&&) = delete; // pretend compiler declared and defined
};
int main()
{
A a = std::declval<A>();
}
error: call to deleted constructor of 'A'
A a = std::declval<A>();
^ ~~~~~~~~~~~~~~~~~
But if the compiler does not implicitly declare a deleted move constructor, then things just work:
#include <type_traits>
struct A
{
A();
A(const A&);
};
int main()
{
A a = std::declval<A>(); // ok
}
Indeed, if the compiler did implicitly declare a deleted move constructor for A, there would be a awful lot of broken C++98/03 code when recompiled in C++11! :-)
I not sure I agree with your summary:
There are basically three states: User Defined, Deleted or Compiler Generated
declared and defined
This means the user has explicitly declared them in the class and provided definitions.
declared and deleted
This means the user has explicitly declared them as deleted (ie they are not available).
undeclared
The user has not provided a declaration (and thus can not provide a definition).
In this case the the compiler will generate a version of the method.
Related
I have this simple program that doesn't compile
#include <future>
class Foo
{
public:
~Foo();
std::future<int> f;
};
Foo getFoo()
{
return Foo();
}
int main()
{
Foo b = getFoo();
}
which, I guess, makes sense. Foo is not copyable because future is not copyable.
In function 'Foo getFoo()':
13:16: error: use of deleted function 'Foo::Foo(const Foo&)'
4:7: note: 'Foo::Foo(const Foo&)' is implicitly deleted because the default definition would be ill-formed:
4:7: error: use of deleted function 'std::future<_Res>::future(const std::future<_Res>&) [with _Res = int]'
In file included from 2:0:
/usr/include/c++/4.9/future:686:7: note: declared here
future(const future&) = delete;
^
In function 'int main()':
18:20: error: use of deleted function 'Foo::Foo(const Foo&)'
What I don't understand is why it compiles when I remove the destructor:
#include <future>
class Foo
{
public:
//~Foo();
std::future<int> f;
};
Foo getFoo()
{
return Foo();
}
int main()
{
Foo b = getFoo();
}
Isn't this destructor generated by default anyway? What effect does it have on the class being copyable/movable?
The implicitly generated copy constructor is defined as deleted because your class contains a std::future, which is not copyable. This means your class is not copyable in either case.
It may however be movable. Usually the example you show could also use a move constructor, but the implicit move constructor is not declared when you declare a destructor manually, making Foo in the first example also not movable, while it is in the second one.
As mentioned by #Ayxan in a comment under the question, since C++17 both your examples would compile, because although Foo isn't movable in the first example, since C++17 mandatory copy elision rules apply and there would only be one Foo constructed directly into Foo b in your example. No temporary Foo objects would exist and the class would not need to be copyable or movable for this.
In general you should always implement copy/move constructor and assignment operators manually if you have a custom destructor. That is known as the rule of 3/5. The language does not currently enforce this rule for the copy operations, although the implicit declaration of the copy operations if a user-declared destructor exists has been deprecated since C++11. The language does however enforce the rule for the move operations by not implicitly declaring the move operations if a user-declared destructor is present.
A custom destructor is not often needed, so you should probably not declare it in the first place. If you need to declare it, because e.g. you need it to be virtual (in which case it should just be defaulted with virtual ~Foo() = default), then you can default the move operations:
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
But if your destructor has a custom definition that does have statements in it that actually perform some work, you likely must implement these methods yourself with proper semantics, so that you don't run into problems when the class is moved.
In c++11, The implicit definition of a copy constructor as defaulted
is deprecated if the class has a user-declared copy assignment
operator or a user-declared destructor.
It's the standard of the language.
Note that you have a noncopyable member too.
I have been playing around with default constructors and noticed a weird behavior (from my point of view).
When I declare A() = default, I get no linker error.
struct A
{
int a;
A() = default;
};
A a; // no linker error
However, when I declare A(); I get it.
struct A
{
int a;
A();
};
A a; // linker error - undefined reference to `A::A()`
Questions:
What's the difference between the two?
And if A(); produces a linker error, why is it supported in the first place? Any practical applications?
UPDATE (Follow-up Question)
For A(); why can't it be implicitly defined by the compiler if no definition is specified by the user?
In the first case the compiler itself defines the constructor.
Take into account that in the first case the constructor declaration is at the same its definition.
In the second case as the constructor is a user-defined constructor then it is the user who must to define the constructor. In the second case there is only a declaration of the constructor.
Take into account that you can declare a constructor and then define it using the specifier default.
For example
#include <iostream>
struct A
{
int a;
A();
};
A::A() = default;
int main()
{
A a;
return 0;
}
The purpose of writing
A();
is to declare to the compiler that a definition of what A() should actually do will be given somewhere else (by you!), and if it is given in another compilation unit (cpp-file) the linker is responsible for finding this definition.
A() = default;
is a way of declaring to the compiler that it should create a definition of what should be done on construction of an A, automatically, subject to the rules of the language. So because the definition is already given, the linker won't complain about not finding it.
Why is it supported to declare without defining A() in the first place? Because you want to be able to compile different cpp-files independently. Otherwise you would always have to compile all your code, even if 99% of it hasn't changed.
The construction of an A will most likely be defined in "A.cpp". If you have completed the design of your struct A then ideally "A.cpp" will be compiled once and never again. If you construct an A in a different class/struct/compilation unit "B.cpp" then the compiler can trust in the existence of a definition for A() while compiling "B.cpp", without knowing what the definition actually looks like.
As to the follow-up question, "why it can't be defined implicitly": this is probably a misunderstanding about why errors occur. Compiler/linker errors do not occur to punish you. They don't mean that the compiler is pretending not to be able to do something although it can. Errors occur in order to remind you that you are breaking your own promises and any attempt by the compiler or the linker to repair that, might be possible, but is most likely not going to work as you want it to, because there are signs that you have lost track of your own requirements.
That being said, A() could be defined implicitely. But if you write "A();" you are explicitely telling the compiler not to do it implicitly, and telling the linker to remind you, if you should ever forget to define it. This doesn't only apply to constructors but to every kind of method, most of which have no natural sense of what it means to define them implicitely. What is the default definition of "A.makeMoney"? It is non-trivial and by writing A.makeMoney(); you are telling the compiler: "trust me, I'm gonna define somewhere how it's gonna be done".
(15.1 Constructors)
A default constructor for a class X is a constructor of class X for
which each parameter that is not a function parameter pack has a
default argument (including the case of a constructor with no
parameters). If there is no user-declared constructor for class X, a
non-explicit constructor having no parameters is implicitly declared
as defaulted (11.4). An implicitly-declared default constructor is an
inline public member of its class.
Purpose of
A() = default;
is to tell compiler to create default constructor, as if no constructor was defined by user. Consider this case
struct A
{
int a;
A(int v): a(v) {}
};
A a; // compiler error, no default constructor
If ANY constructor was declared by user, default one will be gone.
By adding A() = default; to that declaration you would allow class A to be constructed that way. It is explicitly-defaulted (11.4.2)
A function definition whose function-body is of the form = default ;
is called an explicitly-defaulted definition. A function that is
explicitly defaulted shall
(1.1) — be a special member function,
(1.2) — have the same declared function type (except for possibly
differing ref-qualifiers and except that in the case of a copy
constructor or copy assignment operator, the parameter type may be
“reference to non-const T”, where T is the name of the member
function’s class) as if it had been implicitly declared, and
(1.3) — not have default arguments.
Methods follow same linking rules as any functions with external linking. If you declare any method in class body and your code refers to that method (in case of constructor - by creating object of this class), you have to define it in any compilation module of same program, otherwise program will be ill-formed.
struct A
{
A() = default;
Here, you're saying that the constructor should be implemented automagically, i.e. any class members that have a default constructor will be initialized with it, and any class members that don't have a default constructor will be left uninitialized.
struct A
{
A();
Here, you're saying that you will implement a default constructor. So you have to implement it. E.g.
A::A()
: a(42)
{
}
This is additional information, and is supplemental to the answer provided by others.
There is a difference w.r.t. the context of special member functions, when we use the terms such as defaulted, undeclared and deleted.
When a special member function is:
undeclared : It does not participate in overload resolution. To use this functionality, just don't declare the special member function.
deleted : It participates in overload resolution. It prevents compilation, if used anywhere. To use this functionality, the keyword is delete
defaulted : It participates in overload resolution. The default, compiler generated code is provided as the definition. To use this functionality, the keyword is default
There is an interesting talk by Howard Hinnat on the same, where he explains when the special member functions are defaulted/deleted/undeclared - https://www.youtube.com/watch?v=vLinb2fgkHk
Adding more info for A::A();
Referring to class.ctor/1.2:
The class-name shall not be a typedef-name. In a constructor
declaration, each decl-specifier in the optional decl-specifier-seq
shall be friend, inline, explicit, or constexpr.
[ Example:
struct S {
S(); // declares the constructor
};
S::S() { } // defines the constructor
— end example ]
Thus, A(); is just a declaration and not a definition causing:
undefined reference to `A::A()'
I have some legacy code and I need to add a new class for the message (which is irrelevant to my question). But it turns out that I need to declare an empty constructor in order for some static to be initialized. Not a default constructor or compiler-provided, but empty user-defined. I tried to reduce the code to MWE and here what I get:
#include <iostream>
using namespace std;
struct Test
{
Test() {cout << "Test::Test()" << "\n";}
void dummy(){}
};
template<typename T>
struct Message
{
Message()
{
test.dummy(); // this call have to be here in order to initialize Test, but why?
}
static Test test;
};
template<typename T>
Test Message<T>::test;
struct A : public Message<A>
{
//A(){} // uncomment this (and comment the default one) to call the Test constructor
A() = default;
};
int main()
{
}
This is what happening:
The program itself is empty, i.e. no instances are created.
There's a CRTP for an A class, which seems to be critical to the example.
There's a static declaration for the base of A and I'm expecting it's constructor to be called.
There's a dummy call to the function that does nothing, but also critical.
The problem is that if I don't provide a custom constructor then the static constructor never gets called. And I can't understand why do I need this? What's the difference with defaulted or compiler generated? And why do I need to call a dummy function?
I believe there's a rule for that. I checked it with different versions of gcc and clang - the behavior is the same. I very appreciate links to the standard/documentation.
If you leave A constructor defaulted and never call it then there is no need to generate it and therefore no need to create test. If you explicitly default it at definition, call A constructor or access A::test it will be initialized properly.
12.1 Constructors [class.ctor]
7
A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration.
struct A : public Message<A>
{
A() = default; // no constructor is emitted unless A is instantiated
A(); // declaration
};
A::A() = default; // explicit default definition
int
main()
{
A a; // instantiation
A::test; // just explicitly access test so it is initialized regardless of A constructor
}
C++14 [temp.inst]/2:
Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
This says clearly that Message<A>::test will not be initialized unless it is used in a way that requires its definition to exist.
The only expression in your program that would require the definition is test.dummy() in the constructor of Message<A> ; so if that expression is removed then test must not be initialized.
For the case where test.dummy() is present, note that it is inside a template function, the constructor of Message<A>. If this constructor is never instantiated, then test.dummy() will not be considered.
As pointed out by VTT, [class.ctor] says that the explicitly-defaulted constructor for A means that no constructor is defined unless an A is odr-used.
Your code doesn't odr-use an A, therefore A's constructor is not defined, therefore there is no invocation of base class constructor (which would only happen if if A's constructor was defined), therefore the constructor template Message<A>() is not instantiated, therefore test is not required to exist.
I have some legacy code and I need to add a new class for the message (which is irrelevant to my question). But it turns out that I need to declare an empty constructor in order for some static to be initialized. Not a default constructor or compiler-provided, but empty user-defined. I tried to reduce the code to MWE and here what I get:
#include <iostream>
using namespace std;
struct Test
{
Test() {cout << "Test::Test()" << "\n";}
void dummy(){}
};
template<typename T>
struct Message
{
Message()
{
test.dummy(); // this call have to be here in order to initialize Test, but why?
}
static Test test;
};
template<typename T>
Test Message<T>::test;
struct A : public Message<A>
{
//A(){} // uncomment this (and comment the default one) to call the Test constructor
A() = default;
};
int main()
{
}
This is what happening:
The program itself is empty, i.e. no instances are created.
There's a CRTP for an A class, which seems to be critical to the example.
There's a static declaration for the base of A and I'm expecting it's constructor to be called.
There's a dummy call to the function that does nothing, but also critical.
The problem is that if I don't provide a custom constructor then the static constructor never gets called. And I can't understand why do I need this? What's the difference with defaulted or compiler generated? And why do I need to call a dummy function?
I believe there's a rule for that. I checked it with different versions of gcc and clang - the behavior is the same. I very appreciate links to the standard/documentation.
If you leave A constructor defaulted and never call it then there is no need to generate it and therefore no need to create test. If you explicitly default it at definition, call A constructor or access A::test it will be initialized properly.
12.1 Constructors [class.ctor]
7
A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration.
struct A : public Message<A>
{
A() = default; // no constructor is emitted unless A is instantiated
A(); // declaration
};
A::A() = default; // explicit default definition
int
main()
{
A a; // instantiation
A::test; // just explicitly access test so it is initialized regardless of A constructor
}
C++14 [temp.inst]/2:
Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
This says clearly that Message<A>::test will not be initialized unless it is used in a way that requires its definition to exist.
The only expression in your program that would require the definition is test.dummy() in the constructor of Message<A> ; so if that expression is removed then test must not be initialized.
For the case where test.dummy() is present, note that it is inside a template function, the constructor of Message<A>. If this constructor is never instantiated, then test.dummy() will not be considered.
As pointed out by VTT, [class.ctor] says that the explicitly-defaulted constructor for A means that no constructor is defined unless an A is odr-used.
Your code doesn't odr-use an A, therefore A's constructor is not defined, therefore there is no invocation of base class constructor (which would only happen if if A's constructor was defined), therefore the constructor template Message<A>() is not instantiated, therefore test is not required to exist.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What’s the point in defaulting functions in C++11?
C++11 introduced defaulted methods (e.g. void myMethod() = default;).
What does it do to methods (how do methods behave after being defaulted). How do I use them properly (what are its uses)?
There are a number of class members that are considered "special member functions" by the C++ standard. These are:
The default constructor (a constructor that can be called with no parameters).
The copy constructor (a constructor that can be called with one parameter that is the object type as an lvalue reference).
The copy assignment operator (an operator= overload that can be called with one parameter that is the object type as either an lvalue reference or a value).
The move constructor (a constructor that can be called with one parameter that is the object type as an rvalue reference).
The move assignment operator (an operator= overload that can be called with one parameter that is the object type as either an rvalue reference or a value).
The destructor.
These member functions are special in that the language does special things with them on types. Another thing that makes them special is that the compiler can provide definitions for them if you do not. These are the only functions that you can use the = default; syntax on.
The issue is that the compiler will only provide a definition under certain conditions. That is, there are conditions under which a definition will not be provided.
I won't go over the entire list, but one example is what others have mentioned. If you provide a constructor for a type that is not a special constructor (ie: not one of the constructors mentioned above), a default constructor will not be automatically generated. Therefore, this type:
struct NoDefault
{
NoDefault(float f);
};
NoDefault cannot be default constructed. Therefore, it cannot be used in any context where default construction is needed. You can't do NoDefault() to create a temporary. You can't create arrays of NoDefault (since those are default constructed). You cannot create a std::vector<NoDefault> and call the sizing constructor without providing a value to copy from, or any other operation that requires that the type be DefaultConstructible.
However, you could do this:
struct UserDefault
{
UserDefault() {}
UserDefault(float f);
};
That would fix everything, right?
WRONG!
That is not the same thing as this:
struct StdDefault
{
StdDefault() = default;
StdDefault(float f);
};
Why? Because StdDefault is a trivial type. What does that mean? I won't explain the whole thing, but go here for the details. Making types trivial is often a useful feature to have, when you can do it.
One of the requirements of a trivial type is that it does not have a user-provided default constructor. UserDefault has a provided one, even though it does the exact same thing as the compiler-generated one would. Therefore, UserDefault is not trivial. StdDefault is a trivial type because = default syntax means that the compiler will generate it. So it's not user-provided.
The = default syntax tells the compiler, "generate this function anyway, even if you normally wouldn't." This is important to ensure that a class is a trivial type, since you cannot actually implement special members the way the compiler can. It allows you to force the compiler to generate the function even when it wouldn't.
This is very useful in many circumstances. For example:
class UniqueThing
{
public:
UniqueThing() : m_ptr(new SomeType()) {}
UniqueThing(const UniqueThing &ptr) : m_ptr(new SomeType(*ptr)) {}
UniqueThing &operator =(const UniqueThing &ptr)
{
m_ptr.reset(new SomeType(*ptr)); return *this;
}
private:
std::unique_ptr<SomeType> m_ptr;
};
We must write every one of these functions to make the class copy the contents of the unique_ptr; there's no way to avoid that. But we also want this to be moveable, and the move constructor/assignment operators won't automatically be generated for us. It'd silly to re-implement them (and error-prone if we add more members), so we can use the = default syntax:
class UniqueThing
{
public:
UniqueThing() : m_ptr(new SomeType()) {}
UniqueThing(const UniqueThing &ptr) : m_ptr(new SomeType(*ptr)) {}
UniqueThing(UniqueThing &&ptr) = default;
UniqueThing &operator =(const UniqueThing &ptr)
{
m_ptr.reset(new SomeType(*ptr)); return *this;
}
UniqueThing &operator =(UniqueThing &&ptr) = default;
private:
std::unique_ptr<SomeType> m_ptr;
};
Actually, default can only apply to special methods - i.e. constructors, destructors, assignment operator:
8.4.2 Explicitly-defaulted functions [dcl.fct.def.default]
1 A function definition of the form:
attribute-specifier-seqopt decl-specifier-seqopt declarator = default ;
is called an explicitly-defaulted definition. A function that is explicitly defaulted shall
— be a special member function,
— have the same declared function type (except for possibly differing ref-qualifiers and except that in
the case of a copy constructor or copy assignment operator, the parameter type may be “reference to
non-const T”, where T is the name of the member function’s class) as if it had been implicitly declared,
and
— not have default arguments.
They behave the same as if the compiler generated them and are useful for cases like:
class Foo{
Foo(int) {}
};
here, the default constructor doesn't exist, so Foo f; wouldn't be valid. However, you can tell the compiler that you want a default constructor without the need to implement it yourself:
class Foo{
Foo() = default;
Foo(int) {}
};
EDIT: Pointed out by #Nicol Bolas in the comments, this truly doesn't explain why you'd prefer this over Foo() {}. What I'm guessing is: if you have a class w/ implementations separated in an implementation file, your class definition (if you don't use =default) would look like:
class Foo{
Foo();
Foo(int);
};
What I'm assuming is that the =default is meant to provide an idiomatic way of telling you "we're not doing anything special in the constructor". With the above class definition, the default constructor could very well not value-initialize the class members. With the =default you have that guarantee just by looking at the header.
Using = default on a constructor or copy-constructor means that the compiler will generate that function for you during compile-time. This happens normally when you exclude the respective functions from your class/struct. And in the case where you define your own constructor, this new syntax allows you to explicitly tell the compiler to default-construct the constructor where it normally won't. Take for instance:
struct S {
};
int main() {
S s1; // 1
S s2(s1); // 2
}
The compiler will generate both a copy-constructor and a default-constructor, thus allowing us to instantiate an S object like we did (1) and copy s2 into s1 (2). But if we define our own constructor, we find that we are unable to instantiate in the same way:
struct S {
S(int);
};
int main() {
S s; // illegal
S s(5); // legal
}
This fails because S has been given a custom-defined constructor, and the compiler won't generate the default one. But if we still want the compiler to give us one, we can explicitly convey this using default:
struct S {
S(int);
S() = default;
S(const S &) = default;
};
int main() {
S s; // legal
S s(5); // legal
S s2(s); // legal
}
Note, however, that only certain functions with certain function-signatures can be overloaded. It follows that this will fail because it is neither a copy-constructor nor a default-constructor or a move or assignment operator:
struct S {
S(int) = default; // error
};
We are also able to explicitly define the assignment operator (just like the default/copy-constructor, a default one is generated for us when we do not write out our own). So take for example:
struct S {
int operator=(int) {
// do our own stuff
}
};
int main() {
S s;
s = 4;
}
This compiles, but it won't work for us in the general case where we want to assign another S object into s. This is because since we wrote our own, the compiler doesn't provide one for us. This is where default comes into play:
struct S {
int operator=(int) {
// do our own stuff
}
S & operator=(const S &) = default;
};
int main() {
S s1, s2;
s1 = s2; // legal
}
But technically it's superfluous to define the assignment operator, copy, or move constructor as default when there is no other function "overriding" it as the compiler will provide one for you in that case anyway. The only case in which it won't provide you one is where you define your own one (or variation thereof). But as a matter of preference, asking the compiler to provide a default function using the new aforementioned syntax is more explicit and easier to see and understand if intentionally left out for the compiler.