C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Access-level aware concepts

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Sat, 12 Oct 2024 15:03:31 +0100
On Sat, 12 Oct 2024 at 14:59, Jonathan Wakely <cxx_at_[hidden]> wrote:

>
>
> On Sat, 12 Oct 2024 at 14:37, Robin Savonen Söderholm via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> I generally avoid inheritance, but it is (sadly) the only ABI-safe and
>> portable solution (AFAIK) to optimise away empty members.
>>
>
> But doesn't work for final classes, or ones with protected constructors.
> But why would the protected constructor be an issue?
>
> If you're using inheritance instead of using a data member, because you
> want the empty base optimization, then a protected constructor would not
> have been usable anyway. So why do you care about this case?
>

Furthermore, if the `requires constructible_from<T, Ts...>` check was true
for a protected ctor in a derived context, that would make it observable
whether or not your wrapper uses the EBO or uses [[no_unique_address]]
instead. Because it wouldn't be able to use that constructor if the type
was a data member using [[no_unique_address]], but would be able to use
that constructor when the type is a base class. So your wrapper's public
API would change depending on an implementation detail.



> If the type is awkward and unusable and breaks code that tries to use it,
> that's the type's problem. The user who tries to instantiate your class
> template with an unusable type can deal with it.
>
>
>
>> [[no_unique_address]] is not supported by Clang for windows, MSVC only
>> allows the MSVC-prefixed version.
>>
>
> What an absolute s***show that has turned out to be :-(
>
>
>
>> But maybe I should tackle that instead...
>>
>
>
>
>
>>
>> // Robin
>>
>> On Sat, Oct 12, 2024 at 3:27 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>>
>>>
>>>
>>> On Sat, 12 Oct 2024 at 14:22, Jonathan Wakely <cxx_at_[hidden]> wrote:
>>>
>>>>
>>>>
>>>> On Sat, 12 Oct 2024 at 14:05, Robin Savonen Söderholm via Std-Proposals
>>>> <std-proposals_at_[hidden]> wrote:
>>>>
>>>>> Hi!
>>>>> I can't seem to find any information about how constraints and class
>>>>> access specifiers could work together. Currently it seems like concepts are
>>>>> always evaluated from "outside" a class (i.e. only public fields and
>>>>> methods affect the evaluation of the constraint).
>>>>>
>>>>
>>>> Correct. That's essential to be able to cache the result, you don't
>>>> want foo<T> to mean different things depending on where the first check
>>>> happens, and you don't want the result to not be memoized (for performance
>>>> during compilation).
>>>>
>>>>
>>>>
>>>>> E.g. for example:
>>>>> ```c++
>>>>>
>>>>> #include <concepts>
>>>>> #include <utility>
>>>>>
>>>>> class clazz_with_protected_ctor {
>>>>> protected:
>>>>> explicit clazz_with_protected_ctor(int) {}
>>>>> };
>>>>>
>>>>> template <typename T>
>>>>> struct clazz_wrapper: private T {
>>>>> template <typename... Ts>
>>>>> requires(std::constructible_from<T, Ts&&...>) explicit
>>>>> clazz_wrapper(Ts&&... args) : T(std::forward<T>(args)...) {}
>>>>> };
>>>>>
>>>>> void foo() {
>>>>> // Generates compile-error since the constraint for the constructor
>>>>> can't see the protected constructor
>>>>> auto my_wrapper = clazz_wrapper<clazz_with_protected_ctor>(1);
>>>>> }
>>>>> ```
>>>>>
>>>>> I wonder if not the above code should actually be a sensible piece of
>>>>> code (especially with CRTP-based API:s), and it may be needed that
>>>>> constraints are evaluated from the context that they are used.
>>>>>
>>>>
>>>> Inheritance is an incredibly strong coupling, the strongest in C++. It
>>>> doesn't really make sense to be inheriting from types where you don't know
>>>> whether you can use a protected (or private, via friendship) API. Either
>>>> inherit from arbitrary types provided as template args and rely on the
>>>> members you need being public
>>>>
>>>
>>> I should have said "being accessible" rather than necessarily public.
>>> It's fine if the member you need to use is protected, because the derived
>>> class will be able to use it. It doesn't make sense to query whether it's
>>> usable though. If you're inheriting,the member you need to use need to be
>>> accessible
>>>
>>> N.B. In the example above, you could just do `using T::T;` to get the
>>> desired effects. So you don't need to test for the constructor being usable.
>>>
>>>
>>>
>>>> , or don't inherit.
>>>>
>>>
>>>
>>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>

Received on 2024-10-12 14:04:50