Question

According to C++ reference std::swap is equivalent to

T c(std::move(a)); a=std::move(b); b=std::move(c);

This should allow to swap two non copiable but movable object. Therefore I don't understand why

#include<utility>

struct Foo {
  Foo() = delete;
  Foo(int) {};
  Foo(Foo &) = delete;
  Foo(Foo &&) {};
  ~Foo() {};
};

int main() {
  Foo a(1),b(2);
  std::swap(a,b);
}

is refused by the compiler with

In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
                 from /usr/include/c++/4.8/utility:70,
                 from swap.cpp:1:
/usr/include/c++/4.8/bits/move.h: In instantiation of ‘void std::swap(_Tp&, _Tp&) [with _Tp = Foo]’:
swap.cpp:13:16:   required from here
/usr/include/c++/4.8/bits/move.h:176:11: error: use of deleted function ‘Foo& Foo::operator=(const Foo&)’
       __a = _GLIBCXX_MOVE(__b);
           ^
swap.cpp:3:8: note: ‘Foo& Foo::operator=(const Foo&)’ is implicitly declared as deleted because ‘Foo’ declares a move constructor or move assignment operator
 struct Foo {
        ^
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
                 from /usr/include/c++/4.8/utility:70,
                 from swap.cpp:1:
/usr/include/c++/4.8/bits/move.h:177:11: error: use of deleted function ‘Foo& Foo::operator=(const Foo&)’
       __b = _GLIBCXX_MOVE(__tmp);

note: this is with GCC 4.8 and 4.9 but clang complain as well.

Was it helpful?

Solution

You declared a move constructor. However, you need a move assignment operator for std::swap. You should add the following two operators:

auto operator=(const Foo& rhs) & -> Foo& = delete;
auto operator=(Foo&& rhs) & noexcept -> Foo&
{
    // ...
    return *this;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top