Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this code trying to call the copy constructor?

I just spent an inordinate amount of time fiddling with a complilation error in Visual Studio. I have distilled the code into the small compilable example below and tried it on IdeOne and got the same error which you can see here.

I am wondering why the following code tries to call B(const B&) instead of B(B&&):

#include <iostream>

using namespace std;

class A {
public:
    A() : data(53) { }
    A(A&& dying) : data(dying.data) { dying.data = 0; }

    int data;

private:
    // not implemented, this is a noncopyable class
    A(const A&);
    A& operator=(const A&);
};

class B : public A { };

int main() {
    B binst;

    char* buf = new char[sizeof(B)];

    B* bptr = new (buf) B(std::move(binst));

    cout << bptr->data << endl;

    delete[] buf;
}

I didn't explicitly define any constructors, so B(std::move(binst)) should call the compiler generated B(B&&), no?

When I change B to

class B : public A {
public:
    B() { }
    B(B&&) { }
};

It compiles fine. Why is this?

It will be extremely inconvenient if this can't be fixed from the base class because I have a template class which uses placement new and move constructors like the example, and it will require every class that is not copyable (which is not and definitely should not be a requirement for use with my template class) to have an explicitly defined move constructor.

like image 258
Seth Carnegie Avatar asked Jan 24 '12 18:01

Seth Carnegie


2 Answers

If you are using Visual Studio 2010 or 2012, be advised: the compiler does not automatically generate move constructors for you. That wasn't implemented. So you need to write them yourself.

like image 179
Nicol Bolas Avatar answered Oct 10 '22 03:10

Nicol Bolas


You must be facing a compiler bug. The standard says that B gets an implicitly declared and defined move constructor; all the conditions of 12.8(9) are met (i.e. B does not have an explicitly declared copy constructor, copy-assignment, etc, and the move constructor would not implicitly be declared deleted).

like image 31
Kerrek SB Avatar answered Oct 10 '22 02:10

Kerrek SB