Date: Fri, 24 Jan 2025 09:50:27 +0000
On 22/01/2025 15:29, Dennis Gusev via Std-Proposals wrote:
> If you look up "inheriting from STL containers", the top results from SO
> and reddit all mention it being a bad practice since standard containers
> aren't designed to be inherited from.
>
>
> Specifically, they dont have virtual destructors so there's a risk of UB
> from deleting through pointer to base.
P2413 Remove unsafe conversions of unique_ptr<T> is meant to make that
UB less likely to occur, at least when using smart pointers. IMO it's
fine to extend/adapt the interface of standard library types this way,
as long as you are not trying to add overloads.
>
>
> Also if you override any existing member functions and accidentally pass
> your derived class to a function expecting a regular STL container, the
> original base class member functions will get called instead(not to
> mention potential object slicing).
>
>
> What if C++ had a way to publicly inherit from a class and also ban base
> class conversions to avoid potential usage pitfalls with something like
> this:
>
>
> class Base
>
> {
>
> public:
>
> void foo()
>
> {
>
> std::println("Base foo");
>
> }
>
>
> void bar()
>
> {
>
> std::println("Base bar");
>
> }
>
> };
>
>
> class PublicDerived : public Base
>
> {
>
> public:
>
> void foo()
>
> {
>
> std::println("PublicDerived foo");
>
> }
>
> };
>
>
> class ComposedDerived : composed Base // new type of inheritance
>
> {
>
> public:
>
> void foo()
>
> {
>
> std::println("ComposedDerived foo");
>
> }
>
> };
>
>
> void testFoo(Base& val)
>
> {
>
> val.foo();
>
> }
>
>
> int main()
>
> {
>
> PublicDerived publicDerived;
>
> publicDerived.foo(); // prints "PublicDerived foo"
>
> publicDerived.bar(); // accessible, prints "Base bar"
>
> testFoo(publicDerived); // uh oh, prints "Base foo" even though we
> have our own foo
>
>
> ComposedDerived composedDerived;
>
> composedDerived.foo(); // prints "ComposedDerived foo"
>
> composedDerived.bar(); // still accessible, prints "Base bar"
>
> testFoo(composedDerived) // doesn't compile, conversion to base
> forbidden
>
>
> return 0;
>
> }
>
>
> Has anything like this ever been proposed?
>
>
> Seems like it would address a common use case by making it possible to
> extend behavior of classes safely even if they weren't designed to be
> inherited from(i.e. no public virtual or protected nonvirtual destructor)
>
>
> If you look up "inheriting from STL containers", the top results from SO
> and reddit all mention it being a bad practice since standard containers
> aren't designed to be inherited from.
>
>
> Specifically, they dont have virtual destructors so there's a risk of UB
> from deleting through pointer to base.
P2413 Remove unsafe conversions of unique_ptr<T> is meant to make that
UB less likely to occur, at least when using smart pointers. IMO it's
fine to extend/adapt the interface of standard library types this way,
as long as you are not trying to add overloads.
>
>
> Also if you override any existing member functions and accidentally pass
> your derived class to a function expecting a regular STL container, the
> original base class member functions will get called instead(not to
> mention potential object slicing).
>
>
> What if C++ had a way to publicly inherit from a class and also ban base
> class conversions to avoid potential usage pitfalls with something like
> this:
>
>
> class Base
>
> {
>
> public:
>
> void foo()
>
> {
>
> std::println("Base foo");
>
> }
>
>
> void bar()
>
> {
>
> std::println("Base bar");
>
> }
>
> };
>
>
> class PublicDerived : public Base
>
> {
>
> public:
>
> void foo()
>
> {
>
> std::println("PublicDerived foo");
>
> }
>
> };
>
>
> class ComposedDerived : composed Base // new type of inheritance
>
> {
>
> public:
>
> void foo()
>
> {
>
> std::println("ComposedDerived foo");
>
> }
>
> };
>
>
> void testFoo(Base& val)
>
> {
>
> val.foo();
>
> }
>
>
> int main()
>
> {
>
> PublicDerived publicDerived;
>
> publicDerived.foo(); // prints "PublicDerived foo"
>
> publicDerived.bar(); // accessible, prints "Base bar"
>
> testFoo(publicDerived); // uh oh, prints "Base foo" even though we
> have our own foo
>
>
> ComposedDerived composedDerived;
>
> composedDerived.foo(); // prints "ComposedDerived foo"
>
> composedDerived.bar(); // still accessible, prints "Base bar"
>
> testFoo(composedDerived) // doesn't compile, conversion to base
> forbidden
>
>
> return 0;
>
> }
>
>
> Has anything like this ever been proposed?
>
>
> Seems like it would address a common use case by making it possible to
> extend behavior of classes safely even if they weren't designed to be
> inherited from(i.e. no public virtual or protected nonvirtual destructor)
>
>
Received on 2025-01-24 09:50:33