In the code below, I made p const because it will never point to any other int during Foo's lifetime. This doesn't compile, as the unique_ptr's copy constructor is called, which is obviously deleted. Are there any solutions besides making p non-const? Thanks.
#include <memory>
using namespace std;
class Foo
{
public:
//x is a large struct in reality
Foo(const int* const x) : p(x) {};
Foo(Foo&& foo) : p(std::move(foo.p)) {};
private:
const unique_ptr<int> p;
};
The semantics of your move constructor are contradictory.
You have declared a const std::unique_ptr
which will (uniquely) own the value it is initialised with.
But you've declared a move constructor that should move that value into another object at construction.
So what do you think should happen to the std::unique_ptr
in the 'temporary' being move constructed from?
If you want it to be release()
ed you've violated its const
ness.
If you want it to retain its value you've violated the constraint of std::unique
with requires no more than one such object to own any given object.
Checkmate.
This problem reveals a subtle limitation of the C++ language. It requires move
semantics to leave the copied to and from as valid objects.
There are several quite reasonable proposals for 'destructive move' which would in truth better reflect what most uses of move
are doing - take a value to here from there 'invalidating' what was there.
Google them. I haven't made a literature survey so don't want to recommend one.
Your alternatives here are to remove const
or cast it way.
I strongly recommend removing it. You can make sure the semantics of your class ensure the appropriate const-ness with no impact and no 'ugly suspect' const_cast
.
#include <iostream>
#include <memory>
class Foo
{
public:
Foo(const int x) : p(new int(x)) {};
Foo(Foo&& foo) :
p(std::move(foo.p)) {
};
int get(void)const{
return *(this->p);
}
private:
std::unique_ptr<int> p;
};
Foo getMove(){
return Foo(88);
}
int main(){
Foo bar(getMove());
std::cout<<bar.get()<<std::endl;
return EXIT_SUCCESS;
}