19

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.

10
  • Is there a compiler generated B(B&&)? My C++11 is still a bit rusty. And would your B(B&&) need to initialise A(A&&)? Commented Jan 24, 2012 at 18:21
  • @CashCow yes, all it does is move each member (if that's wrong then I'm looking at you, Kerrek SB :)) Commented Jan 24, 2012 at 18:22
  • Compiles fine on GCC 4.6, GCC 4.7, and Clang 3.0. Commented Jan 24, 2012 at 18:22
  • 2
    @CashCow: There should be, but VS2010 doesn't make one. Commented Jan 24, 2012 at 18:22
  • 3
    Works fine on GCC 4.6.2. Commented Jan 24, 2012 at 18:22

2 Answers 2

17

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.

Sign up to request clarification or add additional context in comments.

3 Comments

It should be noted that the details of when a move constructor should be implicitly-defined as defaulted have changed near the end of the standardization process and vc2010 has been around before that. Also, vc2010 does not support = delete, which makes it difficult to talk about conformance of move constructors :)
That is seriously annoying. I long for VS11. Thanks.
@Seth Carnegie: VC11 will not generate automatically move constructor either... blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx "Rvalue references v3.0 adds new rules to automatically generate move constructors and move assignment operators under certain conditions. This will not be implemented in VC11, which will continue to follow VC10's behavior of never automatically generating move constructors/move assignment operators."
6

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).

1 Comment

I guess this is what I get for using VS, a compiler that was written between-standards. Thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.