Date: Sun, 21 Jun 2026 12:11:58 -0400
On Sun, Jun 21, 2026 at 12:32 AM Hewill Kang via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Jens Maurer <jens.maurer_at_[hidden]> 於 2026年6月21日週日 上午2:55寫道:
>
>> On 6/20/26 11:32, Hewill Kang via Std-Proposals wrote:
>> > Hi all,
>> >
>> > After three years, I finally had the opportunity to finish this paper,
>> and I am grateful for any feedback:
>> >
>> > https://isocpp.org/files/papers/D4281R0.html <
>> https://isocpp.org/files/papers/D4281R0.html>
>>
>> I don't follow the second one of the two reasons given for requiring
>> "typename": "Second, it ensures parser simplification."
>>
>> If we can get away without typename for alias-declarations, we sure can
>> get away without typename in requires-expressions, too. Do you have
>> actual
>> compiler implementation experience to the contrary?
>>
>
> The description here is indeed somewhat vague.
> My initial idea was that always requiring typename could be more
> implementation-friendly, since it just adds `using identifier =` to the
> original *type-requirement*, essentially:
>
> *{using identifier =}opt *
> *type-requirement*
> while supporting optional typename might introduce unnecessary complexity
> for implementation.
> Is this reasonable?
>
No. This is the same sort of "skip over a redundant `typename` keyword if
necessary" machinery that all compilers have had since C++20. See P0634
"Down with typename!"
<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0634r3.html> (2018).
That machinery is used in N places already, and it introduces no new
complexity merely to reuse that same machinery in the N+1th place.
The core-language term of art is "type-only context," and so all you have
to do is modify [temp.res.general]
<https://eel.is/c++draft/temp.res.general#def:context,type-only> to say:
> A qualified or unqualified name is said to be in a type-only context if
it is the terminal name of
> - a typename-specifier, type-requirement, nested-name-specifier,
elaborated-type-specifier, class-or-decltype, using-enum-declarator, or
> - a simple-type-specifier of a friend-type-specifier, or
[...]
— wait, actually, in your context it's already a *type-requirement*! So I
think your new grammar could just be:
type-requirement:
`typename` nested-name-specifier_opt type-name `;`
`typename` splice-specifier `;`
`typename` splice-specialization-specifier `;`
type-alias-requirement
type-alias-requirement:
`using` identifier `=` nested-name-specifier_opt type-name `;`
`using` identifier `=` splice-specifier `;`
`using` identifier `=` splice-specialization-specifier `;`
I'd like to see discussion of the ways your *type-alias-requirement*
grammar differs from the grammar of *alias-declaration
<https://eel.is/c++draft/dcl#nt:alias-declaration>*. Why don't you allow
attributes? Why don't you allow the full variety of *defining-type-id*
after the `=`? For example:—
template<class T>
concept Referenceable = requires {
using R = T&;
};
static_assert(!Referenceable<void>);
I think it's fine not to allow these, and the rationale would be something
like: "We don't support `typename T&;` as a *type-requirement* today. We
could, but that's orthogonal to this proposal's feature."
But that should be in the paper.
Now, I don't understand what you're saying here:
> A *type-requirement* that is a *type-alias-requirement* specifies that
the alias denotes the well-formed type.
If I understand your proposed feature correctly, what you need to say is
that the effect of a *type-alias-requirement* is to *introduce a new alias
name* into the scope of its enclosing *requires-expression*.
But I don't see how *what you said* corresponds to that. The switch from
"valid type" to "well-formed type" is also unusual, and must mean
something, but I can't tell what.
HTH,
Arthur
std-proposals_at_[hidden]> wrote:
> Jens Maurer <jens.maurer_at_[hidden]> 於 2026年6月21日週日 上午2:55寫道:
>
>> On 6/20/26 11:32, Hewill Kang via Std-Proposals wrote:
>> > Hi all,
>> >
>> > After three years, I finally had the opportunity to finish this paper,
>> and I am grateful for any feedback:
>> >
>> > https://isocpp.org/files/papers/D4281R0.html <
>> https://isocpp.org/files/papers/D4281R0.html>
>>
>> I don't follow the second one of the two reasons given for requiring
>> "typename": "Second, it ensures parser simplification."
>>
>> If we can get away without typename for alias-declarations, we sure can
>> get away without typename in requires-expressions, too. Do you have
>> actual
>> compiler implementation experience to the contrary?
>>
>
> The description here is indeed somewhat vague.
> My initial idea was that always requiring typename could be more
> implementation-friendly, since it just adds `using identifier =` to the
> original *type-requirement*, essentially:
>
> *{using identifier =}opt *
> *type-requirement*
> while supporting optional typename might introduce unnecessary complexity
> for implementation.
> Is this reasonable?
>
No. This is the same sort of "skip over a redundant `typename` keyword if
necessary" machinery that all compilers have had since C++20. See P0634
"Down with typename!"
<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0634r3.html> (2018).
That machinery is used in N places already, and it introduces no new
complexity merely to reuse that same machinery in the N+1th place.
The core-language term of art is "type-only context," and so all you have
to do is modify [temp.res.general]
<https://eel.is/c++draft/temp.res.general#def:context,type-only> to say:
> A qualified or unqualified name is said to be in a type-only context if
it is the terminal name of
> - a typename-specifier, type-requirement, nested-name-specifier,
elaborated-type-specifier, class-or-decltype, using-enum-declarator, or
> - a simple-type-specifier of a friend-type-specifier, or
[...]
— wait, actually, in your context it's already a *type-requirement*! So I
think your new grammar could just be:
type-requirement:
`typename` nested-name-specifier_opt type-name `;`
`typename` splice-specifier `;`
`typename` splice-specialization-specifier `;`
type-alias-requirement
type-alias-requirement:
`using` identifier `=` nested-name-specifier_opt type-name `;`
`using` identifier `=` splice-specifier `;`
`using` identifier `=` splice-specialization-specifier `;`
I'd like to see discussion of the ways your *type-alias-requirement*
grammar differs from the grammar of *alias-declaration
<https://eel.is/c++draft/dcl#nt:alias-declaration>*. Why don't you allow
attributes? Why don't you allow the full variety of *defining-type-id*
after the `=`? For example:—
template<class T>
concept Referenceable = requires {
using R = T&;
};
static_assert(!Referenceable<void>);
I think it's fine not to allow these, and the rationale would be something
like: "We don't support `typename T&;` as a *type-requirement* today. We
could, but that's orthogonal to this proposal's feature."
But that should be in the paper.
Now, I don't understand what you're saying here:
> A *type-requirement* that is a *type-alias-requirement* specifies that
the alias denotes the well-formed type.
If I understand your proposed feature correctly, what you need to say is
that the effect of a *type-alias-requirement* is to *introduce a new alias
name* into the scope of its enclosing *requires-expression*.
But I don't see how *what you said* corresponds to that. The switch from
"valid type" to "well-formed type" is also unusual, and must mean
something, but I can't tell what.
HTH,
Arthur
Received on 2026-06-21 16:12:17
