4

I have a class where the move assignment is explicit deleted, since the object should not be moveable. But if i assign to an instance of this class using RVO the compiler gives me the error:

main.cpp:12:16: note: candidate function has been explicitly deleted

also the compiler is mentioning the existing copy assignment operator but does not use it.

here is my code (or a (not) running example here):

class foo {
public:
    foo() {}
    foo(foo const& r) {}
    foo(foo&&) = delete;

    foo const& operator=(foo const& r) { return *this; }
    foo const& operator=(foo&& r) = delete;
};

int main(int argc, char **argv) {
    foo bar;
    bar = foo();
    return 0;
}

I found a quite similar post here.

I know I can avoid this by using a temporary. i wonder why every compiler (i tested this with gcc, clang and vs2013) is not able to call the existing copy assignment directly? Is there something I am missing?

Community
  • 1
  • 1
user1810087
  • 4,541
  • 1
  • 34
  • 66

3 Answers3

4

The copy assignment is not called, because the (deleted) move assignment is a better match for overload resolution.

Simply don't declare the move assignment at all. Then the copy assignment will be selected. The implicit move assignment operator won't be generated because the class has a user declared copy constructor, move constructor and copy assignment operator. Any of those will prevent the generation of the implicit move assignment operator.


But if i assign to an instance of this class using RVO

There is no RVO involved here. You create a temporary foo and copy assign it to an existing variable. Copy assignments cannot be elided.

Also, it's quite unusual and inefficient to return by value from an assignment operator.

eerorika
  • 181,943
  • 10
  • 144
  • 256
  • `Also, it's quite unusual and inefficient to return by value from an assignment operator.` that's true and also the comment from erip (`Company likes slower code.`). i was working around a class not designed by me and just wondering the fact why it is happening... – user1810087 May 13 '16 at 18:44
1

Just like std::move() applies a static_cast<>() to force the use of the move assignment/constructor, one can do something similar to force the use of the copy assignment/constructor:

#include <iostream>

class foo
{
public:

    foo() {}
    foo(foo const& r) {}
    foo(foo&&) = delete;

    foo const& operator=(foo const& r) { std::cout << ":)\n"; return *this; }
    foo const& operator=(foo&& r) = delete;
};

int main(int argc, char **argv)
{
    foo bar;
    bar = static_cast<const foo&>(foo());
    return 0;
}
R. 久蔵
  • 177
  • 1
  • 5
  • 13
0

You could use placement new to do this:

#include <iostream>
#include <string>
#include <new>

class foo {
public:

    foo() {}
    foo(foo const& r) {}
    foo(foo&&) = delete;

    foo const& operator=(foo const& r) { return *this; }
    foo const& operator=(foo&& r) = delete;
};

int main(int argc,char **argv)
{
    foo bar;

    //bar = foo();
    bar.~foo();
    new(&bar) foo();

    return 0;
}
wally
  • 9,757
  • 3
  • 34
  • 63