C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Public inheritance with banned conversion to base

From: Dennis Gusev <whyarewestillherejust_at_[hidden]>
Date: Fri, 24 Jan 2025 00:35:52 +0000
Just watched Herb Sutter's talk on reflection and indeed, the "instrumented vector" example is exactly what I was looking for. Reflection is looking more and more peak honestly.
Back to cryosleep until C++26 it seems.

________________________________
From: Robin Savonen Söderholm <robinsavonensoderholm_at_[hidden]>
Sent: 22 January 2025 19:38
To: std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Subject: Re: [std-proposals] Public inheritance with banned conversion to base


I think that this will be quite possible to do with the help of reflections. Seeing the Herb Sutter talk they mention the "instrumentation application" where you essentially takes all the functions from one class, expose them in another class but with added logic around each function. So a more powerful way to achieve what you want seems to be on the way already.

On Wed, Jan 22, 2025, 17:15 Arthur O'Dwyer via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
On Wed, Jan 22, 2025 at 10:48 AM Federico Kircheis via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
On 22 January 2025 15:29:38 UTC, Dennis Gusev via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> 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.

That's not the reason. Even "slicing" isn't the biggest reason. The biggest reason IMO is that "STL types are like a box of chocolates: you never know what you're going to get." The API of a standard library type tends to change in subtle ways with every release, not to mention varying in subtle ways across different vendors. There's no sensible way to "extend" an interface that may change out from under you.

https://quuxplusone.github.io/blog/2018/12/11/dont-inherit-from-std-types/
If you think you do know “what you get” when your type T inherits from std::vector: quick, does your type T have a member function ==, and what does it do? Does it have emplace_back, and if so, what is emplace_back’s return type? Does it have CTAD deduction guides? And so on. It’s not that these questions don’t have answers; it’s that you don’t know the answers (and neither do your coworkers).
[...] If you (or your project, or your company) didn’t write class Foo, then class Foo should not be granted control over the API of your own class. And that’s what you’re doing when you inherit from a base class: you’re granting that class control over your API.

What you can safely do is "composition, not inheritance." Take the STL type and make it a member, not a base. Re-expose exactly the API you care about, through an overload set of member functions that you control.

Protected and public inheritance.
Are they not enough?

Protected and private inheritance allow you to somewhat-disable the derived-to-base conversion, but:
(1) they don't actually take it away, they just make it inaccessible, which can have unwanted effects on overload resolution;
(2) they also make-inaccessible all of the member functions, member types, etc., of the base class. My understanding is that Dennis wants to keep the members accessible, so that you can do e.g. `sonOfVector.size()` and `sonOfVector[i]` but forbid `vector<int>(sonOfVector)`.

This goal will feel much more impossible when you realize that C++23's "explicit object parameter" functions allow us to write not only
    vector(const vector& other); // Dennis wants to prevent passing a SonOfVector to that const vector& parameter
but also
    size_t size(this const vector& self); // But Dennis doesn't want to prevent passing a SonOfVector to that const vector& parameter!
This is related to the perennial impossibility of "strong typedefs."<https://quuxplusone.github.io/blog/2018/06/12/perennial-impossibilities/#strong-typedefs>

–Arthur
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]<mailto:Std-Proposals_at_[hidden]>
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2025-01-24 00:35:58