Consider the object:
class Obj
{
public:
Obj() : val(new int(1)) {}
int& get() {return *val;}
const int& get() const {return *val;}
private:
std::shared_ptr<int> val;
};
As expected, when the object is constructed and copies are made they can all modify the same value through the shared_ptr exposed by Obj.
Obj nonconst1;
Obj nonconst2(nonconst1);
nonconst2.get() = 2;
cout << nonconst1.get() << ", " << nonconst2.get() << endl;
It's also possible to copy-construct a const Obj
object from one of the non const, which seems to do the correct thing in that it allows reading but not writing to the value - as expected the following code results in a compile error:
const Obj const1(nonconst1);
const1.get() = 3;
However it is possible to copy-construct a non-const Obj from the const one, which then does permit the value to be modified.
Obj nonconst3(const1);
nonconst3.get() = 3;
To me this doesn't feel const-correct.
Is there a way to prevent this behaviour, whilst still allowing the copy constructor to work? In my real use case, I still want std containers of Obj to be possible.
No, there isn't, unless you want to store a shared_ptr<const int>
, in which case nobody can access it as non-const.
"To me this doesn't feel const-correct" yet it is: you're simply invoking a non const get
method on a non const Obj
. Nothing wrong with that.
If you really need the behaviour you're after, you could to use something like a const proxy to Obj
but then your clients must be able to handle it of course:
class Obj
{
//...
//original class definition goes here
//...
friend class ConstObj;
};
class ConstObj
{
public:
ConstObj( const Obj& v ) : val( v.val ) {}
const int& get() const { return *val; }
private:
std::shared_ptr<int> val;
};
//usage:
class WorkingWithObj
{
public:
WorkingWithObj();
Obj DoSomethingYieldingNonConstObj();
ConstObj DoSomethingYieldingConstObj();
};
WorkingWithObj w;
Obj nonconst( w.DoSomethingYieldingNonConstObj() );
nonconst.get() = 3;
ConstObj veryconst( nonconst );
veryconst.get() = 3; //compiler error
ConstObj alsoconst( w.DoSomethingYieldingConstObj() );
alsoconst.get() = 3; //compiler error
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With