I understand that most std library implementations choose to implement std::enable_shared_from_this
by storing a std::weak_ptr
in the base class. This leads to the following:
#include <memory>
class Foo : public std::enable_shared_from_this<Foo>
{
public:
std::shared_ptr<Foo> GetSharedBar() const
{
// returns shared_ptr<const Foo> instead of std::shared_ptr<Foo>
return shared_from_this();
// Error in VC++2019 due to mismatch.
}
};
It seems clear to me that despite needing to update the reference count, shared_from_this()
is not actually mutating the target object. This seems like an ideal use for mutable, so that shared_from_this()
can be marked as const
with respect to the derived object.
Why isn't it implemented with mutable
?
To elucidate the answer below: it is implemented with the std::weak_ptr
marked mutable
, but that only allows the std::weak_ptr
to be mutated, not for us to hand off a non-const
to someone else.
class Foo : public std::enable_shared_from_this<Foo>
{
public:
std::shared_ptr<Foo> GetSharedBar() const
{
// error: could not convert from 'shared_ptr<const Foo>' to 'shared_ptr<Foo>'
return shared_from_this();
}
};
class Bla
{
public:
Bla* getThis() const
{
// error: invalid conversion from 'const Bla*' to 'Bla*'
return this;
}
};
But they both work if you remove const
from the functions. The issue is that in a const
member function, the this
pointer is a const
pointer.
As another example, take this:
class kluf
{
const std::string* k;
std::string* getK()
{
// error: invalid conversion from 'const string*' to 'std::string*'
return k;
}
};
Clearly you are not allowed to hand a const
member off to somebody else in a non-const
state. This also goes for the this
pointer, and in a const
function this
is const
.