Search code examples
c++c++11default-constructor

Why C++11 implicitly deletes my default constructor?


I wanted to make my class uncopyable using C++11, before I privately inherited my class from boost::noncopyable. In C++11 I implemented following:

class Foo
{
public:
    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;
};

With this change compilation of a client code (with VS 2013) gives me following error:

..\main.cpp(9): error C2512: 'Foo' : no appropriate default constructor available

My client code is pretty simple:

int main()
{
    Foo foo;
}

Is there any C++11 rule which implicitly deletes default constructor in my case ?


Solution

  • The default constructor for Foo is not deleted, it is simply not defined. An explicitly defaulted/deleted constructor is a user-declared constructor, and this causes an implicit declaration of a default constructor to be inhibited. Foo has a user-declared constructor, the explicitly deleted copy constructor.

    From N3337, §12.1/5 [class.ctor]

    A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted (8.4). ...


    Note that if the default constructor was indeed deleted, the error message would probably have said as much. For instance, if I change the definition of Foo to

    class Foo
    {
    public:
        int &i;
    };
    

    the presence of the data member of reference type implicitly deletes the default constructor. Now, clang and gcc produce the error messages

    error: call to implicitly-deleted default constructor of 'Foo'

    and

    error: use of deleted function 'Foo::Foo()'

    Compare these to the error messages produced by your original example

    error: no matching constructor for initialization of 'Foo'
    error: no matching function for call to 'Foo::Foo()'


    To fix your example, you'll need to explicitly default the default constructor

    Foo() = default;