1

Looking at this question it mentions C++11 and later only:

The move constructor is auto-generated if there is no user-declared copy constructor, copy assignment operator or destructor, and if the generated move constructor is valid (e.g. if it wouldn't need to assign constant members) (§12.8/10).

So if I have the following code:

class Y
{
public:
    Y(const Y&) {}
};

struct hasY {
    hasY() = default;
    hasY(hasY&&) = default;
    Y mem; 
};
hasY hy, hy2 = std::move(hy); //this line fails as expected as Y has a user-defined copy constructor.

Now if I add the default constructor to Y:

Y() {}

The error goes away.
Where does it say that the default constructor causes the creation of the move constructor?

(using VS 2015 update 2)

Community
  • 1
  • 1
tomatoRadar
  • 401
  • 3
  • 11
  • 1
    The default constructor does not cause creation of the move constructor. The error in the code is due to `hasY hy` which cannot be completed since there is no accessible constructor for `mem`. You fix this by providing such a constructor. The compiler error messages should indicate this. It might help if you posted the exact compiler output. – M.M Aug 10 '16 at 05:37
  • @M.M If I have just: hasY hy; and Y does not have the default constructor the error is: hasY::hasY(void)': attempting to reference a deleted function in line with what you are saying. But this still doesn't explain why it builds successfully with hy2 = std::move(hy); present. – tomatoRadar Aug 10 '16 at 05:44
  • yes, the "deleted function" is hasY's constructor, which is deleted because there is no accessible constructor for `mem` – M.M Aug 10 '16 at 05:46

3 Answers3

3
class Y
{
public:
    Y(const Y&) {}
};

This class has no default constructor, so

struct hasY {
    hasY() = default;
    hasY(hasY&&) = default;
    Y mem;  // << requires default ctor
};

the error you were getting had nothing to do with move constructors:

prog.cpp: In function 'int main()':
prog.cpp:13:7: error: use of deleted function 'hasY::hasY()'
  hasY hy;
   ^
prog.cpp:8:5: note: 'hasY::hasY()' is implicitly deleted because the default definition would be ill-formed:
     hasY() = default;

http://ideone.com/u46GWS

kfsone
  • 23,617
  • 2
  • 42
  • 74
0

Where does it say that the default constructor causes the creation of the move constructor?

There is no relationship between the creation of the move constructor and the existence, or lack thereof, of the default constructor.

From the C++11 Standard:

12.8 Copying and moving class objects

...

9 If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

— X does not have a user-declared copy constructor,

— X does not have a user-declared copy assignment operator,

— X does not have a user-declared move assignment operator,

— X does not have a user-declared destructor, and

— the move constructor would not be implicitly defined as deleted.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

It is nothing related to the move constructor It is about the default constructor. Try this:

class Y
{
public:
    Y(const Y&) {}
};

struct hasY {
    hasY() = default;
    hasY(hasY&&) = default;
    Y mem; 
};
hasY hy; // This will cause an error because there is no default constructor

Now if you add the default constructor: Y(){}, the error will go away.


As @M.M commented, The copy constructor will be called in a such case.

You may try this code:

class Y{
public:
    Y(){std::cout << "Default constructor\n";}
    Y(const Y&) {std::cout << "Copy constructor\n";}
};

struct hasY {
    hasY() = default;
    hasY(hasY&&) = default;
    Y mem; 
};

int main(){
    hasY hy;
    hasY h=std::move(hy);
}

It will print:

Default constructor

Copy constructor

If you want to make the class not moveable you should delete the move constructor by yourself Y(Y&&)=delete;

Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160
  • ok, so with a user defined default constructor and copy constructor, wouldn't the move constructor be automatically deleted? i.e. shouldn't hy2 = std::move(hy) fail to compile? – tomatoRadar Aug 10 '16 at 05:50
  • 1
    @tomatoRadar the move constructor would not exist in that case ("not exist" is different to "exist as deleted"), so `hy2 = std::move(hy)` would use the copy-constructor – M.M Aug 10 '16 at 05:52
  • @M.M - I see....this is C++11 behaviour. So the implicitly declared move constructor will be deleted but not participate in overload resolution from C++14. – tomatoRadar Aug 10 '16 at 06:44
  • @tomatoRadar again, there is no implicitly declared move constructor in that case. – M.M Aug 10 '16 at 06:51
  • @M.M Continue about the code snippet in this post. Why [this code snippet](https://godbolt.org/z/vWh4oK8WY) does not compile when mark the move constructor as deleted? Could you please explalin that in more detail for me? – John May 03 '22 at 10:47
  • @John to execute `hasY hy2 = std::move(hy);`, it involves that `hy2.mem` must be constructed from `hy.mem`. If there is a move constructor then the move constructor is selected. You marked it as `delete`, and selecting a deleted function means a compilation error. – M.M May 03 '22 at 21:58