Thomas
Thomas

Reputation: 4255

How do I have a const member move-only object without making my object copyable?

#include<algorithm>
#include<vector>
#include<memory>

class Foo {
 public:
  Foo();

#if 1
  // Destructor for rule of 5.
  ~Foo(){}

  // Move constructor yes.
  Foo(Foo&&) noexcept = default;

  // Move assignment probably won't actually be created because const member variable.
  // Do I need it though? Why would vector need to move-assign?
  Foo& operator=(Foo&&) noexcept = default;

  // Copy no.
  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;
#endif

 protected:
  // It works if non-const. Broken if const.
  const std::unique_ptr<int> ptr;
};

int main()
{
  std::vector<Foo> bar;
  bar.reserve(1);
}

I get the error (with GCC):

static assertion failed: result type must be constructible from value type of input range

But why?

To me it looks like both default and move constructor should be fine. Is this in case e.g. I const_cast away the const and erase a middle element, the vector would maybe try to move-assign to "defrag" the vector? (whereas if it tried to destroy+move-construct, that would work)

In the snipped above unique_ptr is standing in for my own move-only type, so this question is not about pointers.

Upvotes: 1

Views: 253

Answers (1)

eerorika
eerorika

Reputation: 238361

How do I have a const member move-only object without making my object copyable?

Having a move-only member object makes your class implicitly non-copyable, so there is nothing in particular that needs to be done to achieve that.


I get the error

But why?

Because your class is not satisfy the requirements of being MoveInsertable. This is because it is not move constructible.

To me it looks like both default and move constructor should be fine.

Move constructor is not fine because of the member that is not movable. The member is non-movable because it is both non-copyable and const.

In conclusion: You can have a class like this, but it cannot be used with std::vector::reserve because it is neither copyable nor movable.

Upvotes: 3

Related Questions