intrusive_ptr
intrusive_ptr copied to clipboard
Relaxing constraints on complete types?
Right now the spec requires that T is a complete type, I feel like this is a tough requirement since neither shared_ptr
nor unique_ptr
have this requirement. Is there a way to work around the restrictions? The other pointer types have some specific places where completeness is required and other places where it's not. Maybe some detailed rules could be fleshed out here as well.
Yes and no.
It is not possible to define intrusive_ptr<Foo>
where Foo
is incomplete. However, we do have a workaround for this:
GIven class Foo
, we fabricate a complete type
class Foo_fwd : public intrusive_base<Foo_fwd>
{
virtual ~Foo_fwd(); // remember to define this elsewhere.
};
intrusive_ptr<Foo_fwd> foo_ptr; // valid, because `Foo_fwd` is complete.
But it its intrusive_ptr<Foo>
that we would like. We have to make Foo
and Foo_fwd
convertible to each other:
class Foo : public Foo_fwd
{
virtual ~Foo(); // remember to define this elsewhere.
};
int main()
{
foo_ptr.reset(new Foo); // conversion from `Foo*` to `Foo_fwd*` is valid.
auto other = static_pointer_cast<Foo>(foo_ptr); // static_cast'ing from base to derived is also valid.
asserrt(foo_ptr == other);
}
We also have a templated solution here: https://github.com/lhmouse/asteria/blob/fc67e16552943b40acd834fb5101b0b2ab6a5c4f/src/fwd.hpp#L235
The helper function that performs base-to-derived conversion is called unerase_cast
.