Reputation: 4255
#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
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