Date: Mon, 10 Nov 2025 19:03:09 +0000
On Mon, 10 Nov 2025, 18:46 Arthur O'Dwyer, <arthur.j.odwyer_at_[hidden]>
wrote:
> On Mon, Nov 10, 2025 at 1:06 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>> On Mon, 10 Nov 2025, 15:51 Arthur O'Dwyer via Std-Proposals, <
>> std-proposals_at_[hidden]> wrote:
>>
>>> On Mon, Nov 10, 2025 at 1:15 AM 叶易安 via Std-Proposals <
>>> std-proposals_at_[hidden]> wrote:
>>>
>>>> We notice that we have 2 available 'tags' in C++ standard library now:
>>>>
>>>> =====
>>>> class my_iterator { using iterator_concept =
>>>> std::random_access_iterator_tag };
>>>> class my_sender { using sender_concept = std::execution::sender_t; }
>>>> =====
>>>>
>>>> Oops, the first ends with `_tag` and the second ends with `_t`. But
>>>> they share the same effect (to make a class satisfy a particular concept).
>>>> Should we unify them?
>>>> Hmmm, before that let's see where we use `_tag` and `_t` in C++
>>>> standard library.
>>>>
>>>> xxx_t:
>>>> 1. <type_traits>. When we have `add_const<T>::type`, we typedef an
>>>> `add_const_t<T>`.
>>>> 2. Typedef which unifies different platforms. `uint8_t`, `wchar_t`,
>>>> `clock_t`, etc.
>>>> 3. Utility type of global constexpr variable. e.g. nullopt_t,
>>>> unexpected_t, etc.
>>>> 4. Utility type of function overload parameters. e.g.
>>>> unique_lock(defer_lock_t), vector(from_range_t), etc.
>>>>
>>>> xxx_tag:
>>>> 1. Customize xxx_concept in class. e.g. using iterator_concept
>>>> forward/bidirectional/.../random_access_iterator_tag.
>>>>
>>>> Should we rename `std::execution::sender_t` into
>>>> `std::execution::sender_tag`?
>>>> Thank you!
>>>>
>>>
>>> Yes, it certainly seems so (at first glance) to me. Like you, I'm not
>>> aware of any prior art for using `_t` as the suffix for a tag type.
>>>
>>
>> Aren't allocator_arg_t, inplace_t, defer_lock_t etc. tag types?
>>
>
> Not in the same sense. Those are the kind of tag type where we write
> namespace std { struct foo_t {}; constexpr foo_t foo; }
> usercode(std::foo, ...);
>
> sender_t and receiver_t and foo_iterator_tag are the kind of tag type
> where we write
> namespace std { struct foo_tag {}; }
> struct Usercode { using foo_concept = std::foo_tag; };
>
> We do indeed have the same kind of overloaded-English-word problem with
> "tag type" that we have with "traits class," but it's true that sender_t
> and receiver_t are the same kind as foo_iterator_tag and not at all the
> same kind as allocator_arg_t, inplace_t, inplace_type_t, defer_lock_t,
> adopt_lock_t, etc. Nor are they the same kind as std::nullopt_t, nor
> std::monostate.
>
> Using a "tag" suffix is unique to the iterator categories, which are from
>> 30 years ago and that design hasn't been repeated elsewhere in the library.
>>
>
> But that's precisely because no other place in the library has repeated the
> using foo_category = ...;
> using foo_concept = ...;
> design, before now, isn't it? AFAIR the closest we've ever come between
> C++98's iterator concept tags and C++26 S/R concept tags is the (IMO
> ill-advised)
> using is_transparent = void;
>
To be clear, that's really:
using is_transparent = *unspecified*;
But it's common to use void there.
which didn't introduce any new tag types.
>
> –Arthur
>
wrote:
> On Mon, Nov 10, 2025 at 1:06 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>> On Mon, 10 Nov 2025, 15:51 Arthur O'Dwyer via Std-Proposals, <
>> std-proposals_at_[hidden]> wrote:
>>
>>> On Mon, Nov 10, 2025 at 1:15 AM 叶易安 via Std-Proposals <
>>> std-proposals_at_[hidden]> wrote:
>>>
>>>> We notice that we have 2 available 'tags' in C++ standard library now:
>>>>
>>>> =====
>>>> class my_iterator { using iterator_concept =
>>>> std::random_access_iterator_tag };
>>>> class my_sender { using sender_concept = std::execution::sender_t; }
>>>> =====
>>>>
>>>> Oops, the first ends with `_tag` and the second ends with `_t`. But
>>>> they share the same effect (to make a class satisfy a particular concept).
>>>> Should we unify them?
>>>> Hmmm, before that let's see where we use `_tag` and `_t` in C++
>>>> standard library.
>>>>
>>>> xxx_t:
>>>> 1. <type_traits>. When we have `add_const<T>::type`, we typedef an
>>>> `add_const_t<T>`.
>>>> 2. Typedef which unifies different platforms. `uint8_t`, `wchar_t`,
>>>> `clock_t`, etc.
>>>> 3. Utility type of global constexpr variable. e.g. nullopt_t,
>>>> unexpected_t, etc.
>>>> 4. Utility type of function overload parameters. e.g.
>>>> unique_lock(defer_lock_t), vector(from_range_t), etc.
>>>>
>>>> xxx_tag:
>>>> 1. Customize xxx_concept in class. e.g. using iterator_concept
>>>> forward/bidirectional/.../random_access_iterator_tag.
>>>>
>>>> Should we rename `std::execution::sender_t` into
>>>> `std::execution::sender_tag`?
>>>> Thank you!
>>>>
>>>
>>> Yes, it certainly seems so (at first glance) to me. Like you, I'm not
>>> aware of any prior art for using `_t` as the suffix for a tag type.
>>>
>>
>> Aren't allocator_arg_t, inplace_t, defer_lock_t etc. tag types?
>>
>
> Not in the same sense. Those are the kind of tag type where we write
> namespace std { struct foo_t {}; constexpr foo_t foo; }
> usercode(std::foo, ...);
>
> sender_t and receiver_t and foo_iterator_tag are the kind of tag type
> where we write
> namespace std { struct foo_tag {}; }
> struct Usercode { using foo_concept = std::foo_tag; };
>
> We do indeed have the same kind of overloaded-English-word problem with
> "tag type" that we have with "traits class," but it's true that sender_t
> and receiver_t are the same kind as foo_iterator_tag and not at all the
> same kind as allocator_arg_t, inplace_t, inplace_type_t, defer_lock_t,
> adopt_lock_t, etc. Nor are they the same kind as std::nullopt_t, nor
> std::monostate.
>
> Using a "tag" suffix is unique to the iterator categories, which are from
>> 30 years ago and that design hasn't been repeated elsewhere in the library.
>>
>
> But that's precisely because no other place in the library has repeated the
> using foo_category = ...;
> using foo_concept = ...;
> design, before now, isn't it? AFAIR the closest we've ever come between
> C++98's iterator concept tags and C++26 S/R concept tags is the (IMO
> ill-advised)
> using is_transparent = void;
>
To be clear, that's really:
using is_transparent = *unspecified*;
But it's common to use void there.
which didn't introduce any new tag types.
>
> –Arthur
>
Received on 2025-11-10 19:03:26
