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! :-)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…