7
struct A
{
    A(int x)
        : n(x)
    {}

    A(A&&)
    {}

    A& operator =(A&&)
    {
        return *this;
    }

    int n;
};

int main()
{
    A a(1), b(2);

    a = b;

    if (2 == a.n)
    {
        // It SHOULD go here!
    }
}

As per the C++ standard 12.8.7:

If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted;

and 12.8.18

If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted;

The statement a = b; should trigger a compiler error. However, my compiler (VC++ 2013 RC) accepts it and calls the implicitly-defined copy assignment instead.

Is this a compiler's bug?

Update:

I have submitted this issue as a bug to microsoft.

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • 1
    "Is this a compiler's bug?" it wouldn't surprise me. MSVC handling of move ctors and move assignment op has always been lacking. – Angew is no longer proud of SO Oct 09 '13 at 08:50
  • `a = b` wouldn't call the copy constructor, would it? – Luchian Grigore Oct 09 '13 at 08:51
  • 3
    Isn't `a = b` a copy-assignment here? Your quote says the copy-constructor is deleted, not the copy-assignment operator. – Useless Oct 09 '13 at 08:52
  • @Useless, because the copy-assignment should have been deleted, so it will trigger an error. – xmllmx Oct 09 '13 at 08:56
  • @xmllmx why should the copy-assignment have been deleted? Either you posted the wrong quote, or read it wrong. – Luchian Grigore Oct 09 '13 at 08:57
  • @xmllmx if there is a quote from the standard saying copy assignment is also deleted, you should include that too. – juanchopanza Oct 09 '13 at 08:57
  • It does trigger a compilation error for `a=b` with GCC, looks like a bug in VC++ to me. The error message from GCC is `error: use of deleted function 'A& A::operator=(const A&)'` and `note: 'A& A::operator=(const A&)' is implicitly declared as deleted because 'A' declares a move constructor or move assignment operator` – Daniel Frey Oct 09 '13 at 08:59
  • 2
    @juanchopanza, my fault. I have added another quote. – xmllmx Oct 09 '13 at 09:01
  • Seeing as you have a user-provided move assignment operator, I believe that you're right. This shouldn't compile. – Agentlien Oct 09 '13 at 09:09
  • Could you please add more blank lines to your example, to make it more readable? – Viktor Sehr Oct 09 '13 at 09:19
  • Couldn't the compiler see that there are no more uses of b in the function and optimize it to a move? – RedX Oct 09 '13 at 09:23
  • @RedX: The compiler generally can't just transform copies into moves except for some very specific circumstances. Standard C++ says that this is a copy so that's what it is and that is why it needs the copy-assignment-operator, even if for some reason the compiler actually could decide to omit using it (or compile it down to a nop). Having the compilability of code depend on the optimization capabilities of the compiler wouldn't be a good idea afterall. – Grizzly Oct 09 '13 at 13:59
  • @Grizzly Thanks for clarifying that, i always thought the compiler could do whatever it wanted under the 'as-if' rule. – RedX Oct 09 '13 at 14:23
  • @RedX The "as-if" rule states that the compiler can do whatever it wants - as long as it is does not change the semantics of the code. Calling the copy constructor instead of failing to compile doesn't fall under this, and so it isn't allowed. – Agentlien Oct 10 '13 at 07:56

1 Answers1

2

This seems like a compiler bug indeed.

Since you have defined a user-provided move assignment operator, the copy assignment operator should be implicitly defined as deleted (as specified in 12.8.18). This is the behaviour exhibited by other compilers (gcc, for example).

Agentlien
  • 4,996
  • 1
  • 16
  • 27