Search code examples
c++constructorcopydefaultauto

Why is a class member variable calling a deleted copy constructor, but local variable calling constructor?


I'm trying to define a member variable for a class using an existing class type that deletes a the its copy constructor. When I try to define the member variable I get a compile time error

test2.cpp:25:24: error: use of deleted function 'UseDelDef::UseDelDef(UseDelDef&&)

But, when I instead define a local variable, there are no issues. I realize the definition of the member variable is calling the default constructor for the class... how do I work around this without changing the existing class? I'm a bit of a c++ n00b... ;) For reference, I'm stuck with c++14

Here's the code for test2.cpp:

class DelDef
{
public:
  DelDef() {}
private:
  DelDef(const DelDef &other) = delete;
};

class UseDelDef
{
public:
  UseDelDef()
  {
    // This is fine...
    DelDef del_def;
  }
private:
   // This calls the default constructor
   // causes a compile error 'use of deleted function'
   DelDef m_del_def;
};

int main()
{
  auto udd = UseDelDef();
}

Solution

  • // This is fine...
    DelDef del_def;
    

    This is fine because it uses default initialisation. DelDef and UseDelDef are both default initialisable.

    auto udd = UseDelDef();
    

    Prior to C++17, this value initialises a temporary UseDelDef (which is fine) and then copy-initialises udd from the temporary (by move). This is ill-formed because UseDelDef is not movable (because DelDef is not movable (because of the deleted copy constructor)).

    Since C++17, the program is well-formed because udd is initialised directly from the expression that is used to initialise the prvalue expression, and there is no temporary object involved (this change of rules was called "guaranteed copy elision"). You can fix it for pre-C++17 simply by using default initialisation instead of copy initialisation just like you used in the constructor:

    int main()
    {
        UseDelDef udd;
    }
    

    Or you could use a C++17 conforming compiler.