Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
455 views
Welcome To Ask or Share your Answers For Others

1 Answer

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! :-)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...