C++ Logo

std-proposals

Advanced search

Re: [std-proposals] How should we tag a class? Use an empty base class or a typedef?

From: Gašper Ažman <gasper.azman_at_[hidden]>
Date: Tue, 28 May 2024 00:55:00 +0100
Arthur,

The whole reason to even have std::is_elide_v separate is because you can't
necessarily change your own widget. Like, I have one called initializer_t,
I want to use it as if it were std::elide, but I can't fix it to have the
nested typedef, perhaps because I don't have write access.

I agree the nested typedef is better when you can default your external
trait to check for the typedef and that makes it easy, but the external
mechanism is way more robustly usable.

So, both, maybe?

On Tue, May 28, 2024, 00:48 Arthur O'Dwyer via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Mon, May 27, 2024 at 4:50 PM Frederick Virchanza Gotham via
> Std-Proposals <std-proposals_at_[hidden]> wrote:
>
>> On Mon, May 27, 2024 at 4:04 PM Gašper Ažman wrote
>> >
>> > strongly against a baseclass. The reason anyone would use anything but
>> > std::elide is because they have their own, and changing that is
>> > difficult.
>> >
>> > Request a `bool std::is_elider_v<my-class>` specialization and then
>> > have `template <typename X> concept elider =
>> std::is_elider_v<remove_cvref_t<X>>`.
>>
>> I think that's more complicated than just having:
>>
>> class elide {
>> public:
>> typedef true_type tag_elide;
>> };
>>
>> Plus, my strategy has the added versatility of being able to override
>> it in a derived class with "false" instead of "true":
>>
>> class MyElide : public std::elide {
>> public:
>> typedef std::false_type tag_elide;
>> };
>>
>
> I agree that Gašper's suggestion of an ad-hoc free-floating
> `is_foo_v`/`is_foo` variable/class template is not optimal. C++20 Ranges
> ended up with a soup of free-floating templates of that form — some
> variable templates, some class templates — and it's just icky.
> A member typedef is generally the way to go. However, in any
> member-typedef-based design that's intended for a *widely reusable
> library*, I strongly recommend the pattern
> struct MyT {
> using is_library3_thing = MyT; // as seen in libc++'s
> __trivially_relocatable
> };
> template<class X> concept library3_thing = std::is_same_v<typename
> X::is_library3_thing, X>;
> rather than either of the state-of-the-art approaches
> struct MyT {
> using is_library1_thing = void; // as seen in C++14's is_transparent
> using is_library2_thing = true_type; // as seen in C++11's
> propagate_on_container_copy_assignment
> };
> template<class X> concept library1_thing = requires { typename
> X::is_library1_thing; };
> template<class X> concept library2_thing = X::is_library2_thing::value;
> The reason is inheritance.
> struct MyU : public MyT {};
> If `MyU` inherits from `MyT`, then it is_library1_thing by definition and
> there's no way to change that.
> It's also is_library2_thing by default, unless the author of `MyU` has the
> presence of mind to define `using is_library2_thing = false_type;` in the
> body of `MyU`.
> But it's *not* is_library3_thing by default. You have to re-opt-in to
> `is_library3_thing` at each level of inheritance (that is, at each leaf).
> This is what you want for most traity things, and I think it's what you'd
> want for your `elide` thingie, too. (Mind you, I don't think your `elide`
> thingie makes enough sense to say anything really concrete about what it
> "should" be like.)
>
> –Arthur
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2024-05-27 23:55:13