C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [Resurrected Proposal] Concept introduces a typename

From: Михаил Найденов <mihailnajdenov_at_[hidden]>
Date: Mon, 8 May 2023 10:08:48 +0300
Updated the proposal, adding comparison with other "modern" languages and
well an example, regarding constraints on multiple types.

On Sat, May 6, 2023 at 9:10 AM Михаил Найденов <mihailnajdenov_at_[hidden]>
wrote:

> Updated the proposal, fixing typos and adding a section Details
>
> There it is proposed to let function(Foo Bar) always mean argument Bar of
> type Foo. In other words, to have a concept introduce a typename,
> one will also have to have a parameter name (or __ of some sort) much like
> it is with regular variables.
>
> On Wed, May 3, 2023 at 5:27 AM Barry Revzin via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>
>>
>> On Tue, May 2, 2023 at 11:37 AM Gašper Ažman via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> I'd be strongly opposed to introducing a yet another syntax to introduce
>>> dependent names. There's nothing wrong with current template-heads.
>>>
>>
>> +1. Over time I've come to the position that the terse syntax
>> (specifically Concept auto, not auto by itself) was not a good idea. It's
>> just pretty rare that it's even viable - you pretty regularly need the
>> type, have a multi-parameter constraint, want multiple parameters of the
>> same type, or have a constraint that you can't express using the terse
>> syntax. Occasionally I'll see something in our codebase that takes a
>> "std::integral auto val" or something, and be mildly shocked that it
>> worked.
>>
>> If we want to cut some characters, there is room for improvement in the
>> longer syntax.
>>
>> To start with, the leading template keyword is unnecessary. This was
>> pointed out during the terse concepts discussions. Declarations can't start
>> with <, so it's unambiguous to both the compiler and the reader what this
>> means:
>>
>> <class T> auto min(T const&, T const&) -> T const&;
>>
>> That's 9 (or 8, if you don't put the space) characters gone, with the
>> added benefit that it starts becoming reasonable to fit a whole declaration
>> on one line. This is still longer than the proposed syntax, but only
>> marginally so:
>>
>> <Sortable S> void f(S x);
>> void f(Sortable S x);
>>
>> And doesn't lead to any additional questions about what reusing the same
>> identifier means in multiple parameters. The paper says:
>>
>> [](Number auto x, decltype(x) y) { } //< current
>> [](Number N x, N y) { }` //< **proposed**
>>
>> Are those supposed to be equivalent? The former allows a call (1, 2L),
>> the latter seems like it would require both parameters to be the same type,
>> which we can already write in marginally more characters today:
>>
>> [](Number N x, N y)
>> []<Number N>(N x, N y)
>>
>> What I'm suggesting just allows the same in function templates:
>>
>> auto gcd(integral T l, T r) - T;
>> <integral T> auto gcd(T l, T r) -> T;
>>
>> Next, I would like to make the following claims:
>>
>>
>> 1. Type template parameters are *overwhelmingly* more common than
>> non-type or template template parameters.
>> 2. Anonymous non-type template parameters are not especially valuable
>> to support, and with the coming addition of _ as a placeholder, are a waste
>> of syntax space.
>>
>> Put those together, and it offers the ability to drop typename/class.
>> It's one of those weird things in C++ where we have two exact synonyms, so
>> people have pointless (in the grand scheme of things) style discussions
>> about which to use - typename conveys that it's any type, but class is
>> shorter. Well, maybe just put neither:
>>
>> <T> auto min(T const&, T const&) -> T const&;
>>
>> The reason I bring up (2) is that today this could've meant an unnamed
>> value of type T. It's not possible today, because you can't omit the
>> template keyword today, but a similar transformation in lambdas is valid
>> code today (well, at least writing <T> could be, it falls apart quickly
>> after that):
>>
>> auto min = []<T>(T const& x, T const& y) -> T const& { ... }
>>
>> Omitting a name for a non-type template parameter is even less useful in
>> lambdas than in function templates. You could *only* call it as
>> f.operator()<1>() anyway? Making the user write that mess just to ignore
>> the value seems very rude. Maybe we could reclaim the syntax.
>>
>> The reason for dropping class/typename is to also suggest another, more
>> adventurous direction. Changing which side of the type we put the
>> constraint on. That is:
>>
>> <T: integral> auto gcd(T l, T r) -> T;
>> <V: view + forward_range> class some_range_adapter { ... };
>>
>> There are two, unrelated motivations for this ordering:
>>
>> First, It allows putting multiple constraint-ids in there, which does
>> come up a lot, and it's a pretty clear way of doing so. We can fight over
>> whether the grouping should be + or &&, or split the difference and call it
>> &.
>>
>> Second, As more code moves to C++20, template-heads are becoming more
>> ambiguous to the reader. Here's an example, what does this mean:
>>
>> template <Some Thing>
>>
>> What is Thing?
>>
>> - A type, constrained on the concept named Some?
>> - A value, whose type is Some?
>> - A value, whose type is some specialization of the class template
>> Some, whose type will be deduced by CTAD?
>>
>> Non-type template parameters, now that they can be class types too, are
>> going to steadily become more and more common. It'd be nice to have some
>> differentiation for the reader.
>>
>> But even if we don't do this last part, dropping template/class/typename
>> seems pretty nice.
>>
>> Barry
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>

Received on 2023-05-08 07:09:02