Date: Mon, 17 Oct 2022 17:55:19 +0100
If you're still interested, Mike Spertus' P2677R0 looks similar to what
you're after.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2677r0.pdf
On Sat, 1 Oct 2022 at 11:14, Oleksandr Koval <oleksandr.koval.dev_at_[hidden]>
wrote:
> That version of Edward looks 100% in line with current syntax but it's too
> verbose for me. It requires too much typing even for simple cases.
> In the realm of universal template parameters I'd like to have:
>
> auto:[V<T>] v = std::vector<int>{}; // V = std::vector, T = int
>
> void f(const auto:[V]& v);
>
> auto:[T1, T2] [key, value] = get_pair();
>
> Why should we type those `template, class, int` inside [] if it's clear
> that it is a placeholder for a template parameter? Taking into account that
> this feature is supposed just to provide access to deduced type, I see no
> reason to allow it to constrain a kind of template parameters
> (type/non-type/template) or parameters themselves with concepts.
>
> Compiler can transform the above into:
>
> template<template auto V, template auto T>
> void deduce_v(V<T>);
>
> On Fri, Sep 30, 2022 at 8:31 PM Edward Catmur via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Fri, 30 Sept 2022 at 17:38, Lénárd Szolnoki via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> Hi,
>>>
>>> One more syntax proposal that extends P1985's unkiversal template
>>> parameter: `template auto`
>>>
>>> 1. allow `template auto` in any deduced context, for example
>>> `vector<template auto> vec = get_vec();`
>>> 2. use the syntax `template<class T> auto` to introduce the name `T`.
>>>
>>
>> Again, syntax. How on earth do you parse this? `template auto` in P1985's
>> usage is fine, since it's just alternate for *template-parameter* (or
>> *type-parameter*), with an alternation on the token `template` with
>> *template-head* resolved immediately at the next token (`auto` vs. `<`).
>> `vector<auto>` is similarly fine, since `auto` is already a
>> *simple-type-specifier*, so that's just a semantic relaxation.
>>
>> template<class T> auto x = foo()
>>> vector<template<class V> auto> v = get_vec()
>>>
>>> Some extra stuff:
>>> * Introducing a name is optional, you can use `template<class> auto` for
>>> a type placeholder, instead of a universal one
>>> * you can have nttp or template placeholders too
>>>
>>> std::array<string, template<size_t arr_size> auto> arr = get_arr();
>>>
>>> A bit verbose compared to my previously proposed auto<class T>.
>>> Honestly, I like that more, but I could live with this.
>>>
>>> I definitely wouldn't want a syntax where you are required to
>>> immediately repeat the introduced name.
>>>
>>
>> Repeating the name means that you can specify its kind (type, class
>> template, value, etc.) and easily see which names are introduced into scope.
>>
>> I really don't see the necessity to golf everything; C++ is already
>> notoriously hard to parse and you want to make it even harder?
>>
>>
>>> Cheers,
>>> Lénárd
>>>
>>> On 30 September 2022 15:01:58 BST, Edward Catmur via Std-Proposals <
>>> std-proposals_at_[hidden]> wrote:
>>>>
>>>>
>>>>
>>>> On Fri, 30 Sept 2022 at 14:19, Oleksandr Koval <
>>>> oleksandr.koval.dev_at_[hidden]> wrote:
>>>>
>>>>> Sorry if this was already discussed, I like `auto<class T>` syntax but
>>>>> the problem I see is this:
>>>>>
>>>>> std::vector<int> f();
>>>>> auto<class T> v = f(); // should T be `std::vector<int>` or just `int`?
>>>>>
>>>>
>>>> That syntax would work as a 2-step process: first you declare entities,
>>>> then deduce them. The declaration and deduction should be pretty much the
>>>> same as for (non-terse) function templates.
>>>>
>>>> So T is repeated:
>>>>
>>>> auto<class T> T v = f();
>>>>
>>>> or
>>>>
>>>> auto<class T> std::vector<T> v = f();
>>>>
>>>> or
>>>>
>>>> auto<template<class> class TT, class T> TT<T> v = f();
>>>>
>>>>
>>>> It’s a bit confusing when you see them side by side. Because of that I
>>>>> don’t think that using angle brackets is a good idea (at least I can’t find
>>>>> any form which is not confusing). We need a new syntax which will clearly
>>>>> show that typename(s) is closely related to `auto` itself. For example:
>>>>>
>>>>> auto:[class T] v = f();
>>>>> auto:[class T1, classT2] [key, value] = get_pair();
>>>>>
>>>>> On Fri, Sep 30, 2022 at 4:07 AM Edward Catmur via Std-Proposals <
>>>>> std-proposals_at_[hidden]> wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> On Thu, 29 Sept 2022 at 21:44, Arthur O'Dwyer <
>>>>>> arthur.j.odwyer_at_[hidden]> wrote:
>>>>>>
>>>>>>> On Thu, Sep 29, 2022 at 3:57 PM Lénárd Szolnoki via Std-Proposals <
>>>>>>> std-proposals_at_[hidden]> wrote:
>>>>>>>
>>>>>>>> On 29 September 2022 20:25:06 BST, Edward Catmur <
>>>>>>>> ecatmur_at_[hidden]> wrote:
>>>>>>>> >On Thu, 29 Sept 2022 at 18:15, Lénárd Szolnoki via Std-Proposals <
>>>>>>>> std-proposals_at_[hidden]> wrote:
>>>>>>>> >
>>>>>>>> >> I think this could be addressed by two distinct proposals.
>>>>>>>> >>
>>>>>>>> >> 1. allow placeholders to appear in any deduced context
>>>>>>>> (std::vector<auto>)
>>>>>>>> >> 2. allow a placeholder to introduce a name (auto<class T>,
>>>>>>>> auto<int i>
>>>>>>>> >> might appear as a deduced nttp)
>>>>>>>> >>
>>>>>>>> >> Then you can have your vector<auto<class T>> to deduce the value
>>>>>>>> type and
>>>>>>>> >> introduce the name T for that.
>>>>>>>> >
>>>>>>>> >std::vector<auto> is problematic, because elsewhere auto means a
>>>>>>>> value of
>>>>>>>> >unconstrained type (e.g. in template<auto>).
>>>>>>>>
>>>>>>>> I disagree. auto is a placeholder for the type of the non-type
>>>>>>>> parameter. If you don't omit the name, then that name refers to the value.
>>>>>>>>
>>>>>>>
>>>>>>> FWIW, I tend to agree with Lénárd here: `auto *p,
>>>>>>> std::unique_ptr<auto> q` seems quite reasonable to me.
>>>>>>>
>>>>>>
>>>>>> Ye-esss; looking at the grammar; `auto` is always a
>>>>>> placeholder-type-specifier, which is a simple-type-specifier, so it makes
>>>>>> sense that it takes the place of a concrete (or inferred) type.
>>>>>>
>>>>>> So Lénárd, I apologise; you're correct that in these contexts `auto`
>>>>>> designates a type, not a value. I'm still trying to get my head round
>>>>>> "template<auto> int f();", but the syntax is clear.
>>>>>>
>>>>>> *However*, I foresee practical problems with allowing auto *anywhere*
>>>>>>> in a declaration. Consider
>>>>>>> template<class T> void f(T t); // since C++98
>>>>>>> template<class T> void g(decltype(T(1)) t); // since C++11
>>>>>>> void f(auto t); // since C++20, equivalent to f #1
>>>>>>> void g(decltype(auto(1)) t); // since C++23, *not* equivalent
>>>>>>> to g #1
>>>>>>>
>>>>>>> Now, the `T` parameter to `g` is not deducible, so "obviously" the
>>>>>>> `auto` in g #2 doesn't mean the same thing as the `auto` in f #2. But are
>>>>>>> you sure we can teach that to the computer?
>>>>>>>
>>>>>>> (Background: I teach that `auto` since C++14 has (like most C++
>>>>>>> keywords) had two meanings: concrete type *inference*, as in auto x
>>>>>>> = 1, and templatey type *deduction*, as in [](auto x){}. The
>>>>>>> physical mechanisms behind, and consequences of, these two usages of `auto`
>>>>>>> are vastly different, although their human-level meaning is similar: "I
>>>>>>> don't want to bother with types; compiler, please figure it out." So if you
>>>>>>> see me talking about "inference" versus "deduction," or "the first meaning
>>>>>>> of auto" versus "the second meaning of auto," that's what I'm talking
>>>>>>> about.)
>>>>>>>
>>>>>>
>>>>>> The deduction process is ultimately the same; both end up in
>>>>>> temp.deduct.call. In an abbreviated function template or generic lambda,
>>>>>> the deduction can be overridden by explicit template argument, but that's a
>>>>>> relatively minor effect. And syntactically, they're the same; a
>>>>>> decl-specifier of a decl-specifier-seq (of a function parameter or variable
>>>>>> declaration); `auto` in a function return type or trailing return type has
>>>>>> less in common, though I'd suppose you'd class that as inference. Still, I
>>>>>> guess it's OK to teach it that way.
>>>>>>
>>>>>> It would certainly *not* be reasonable to have a rule like "Try to
>>>>>>> interpret every `auto` as deduction, but if that would result in a
>>>>>>> non-deducible template parameter, then backtrack and assume it's inference
>>>>>>> instead." It would be reasonable to have a rule that boils down to "Inside
>>>>>>> the operand of a decltype or sizeof or array bound, the `auto` always means
>>>>>>> inference not deduction." But is `g` above the *only* problem
>>>>>>> case? Are there other corner cases where `auto` is already legal today,
>>>>>>> and/or we wouldn't want it to mean a template parameter?
>>>>>>> void f(A<auto(int())>); // is this concrete A<0> or templatey
>>>>>>> A<T(int())>? I guess the type of A will disambiguate...
>>>>>>>
>>>>>>
>>>>>> Currently a placeholder can appear as the decl-specifier of a
>>>>>> function parameter, variable declaration, or template parameter or, as
>>>>>> exactly one simple-type-specifier of a return or trailing return type,
>>>>>> conversion function id, new expression's type id, or (`auto` only) as the
>>>>>> type specifier of a functional cast. If these were relaxed, I think we'd
>>>>>> probably be OK; you just go through inventing extra type template
>>>>>> parameters and perform deduction as usual.
>>>>>>
>>>>>> Also I don't think ambiguity *can* be an issue, or it would be
>>>>>> already; there must be disambiguators in the syntax. Indeed, I have a
>>>>>> strong suspicion that your `A<auto(int())>` is a most vexing parse.
>>>>>>
>>>>>> Also consider that while
>>>>>>> void h1(std::vector<auto, auto> v);
>>>>>>> would work fine with Lénárd's proposed syntax,
>>>>>>> void h2(std::array<auto, ??> a);
>>>>>>> would not. That does seem mildly problematic. However, maybe it's
>>>>>>> consistent with C++20, which permits
>>>>>>> template<class T> concept Integral = true;
>>>>>>> template<Integral T> void ij(); // since C++20
>>>>>>> but not
>>>>>>> template<int N> concept Odd = true;
>>>>>>> template<Odd N> void ij(); // error: Odd does not constrain a
>>>>>>> type
>>>>>>>
>>>>>>
>>>>>> Yes, fair enough; this does conform to the grammar.
>>>>>> --
>>>>>> Std-Proposals mailing list
>>>>>> Std-Proposals_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Regards,
>>>>> Oleksandr Koval.
>>>>>
>>>> --
>>> Std-Proposals mailing list
>>> Std-Proposals_at_[hidden]
>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
>
> --
> Regards,
> Oleksandr Koval.
>
you're after.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2677r0.pdf
On Sat, 1 Oct 2022 at 11:14, Oleksandr Koval <oleksandr.koval.dev_at_[hidden]>
wrote:
> That version of Edward looks 100% in line with current syntax but it's too
> verbose for me. It requires too much typing even for simple cases.
> In the realm of universal template parameters I'd like to have:
>
> auto:[V<T>] v = std::vector<int>{}; // V = std::vector, T = int
>
> void f(const auto:[V]& v);
>
> auto:[T1, T2] [key, value] = get_pair();
>
> Why should we type those `template, class, int` inside [] if it's clear
> that it is a placeholder for a template parameter? Taking into account that
> this feature is supposed just to provide access to deduced type, I see no
> reason to allow it to constrain a kind of template parameters
> (type/non-type/template) or parameters themselves with concepts.
>
> Compiler can transform the above into:
>
> template<template auto V, template auto T>
> void deduce_v(V<T>);
>
> On Fri, Sep 30, 2022 at 8:31 PM Edward Catmur via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> On Fri, 30 Sept 2022 at 17:38, Lénárd Szolnoki via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> Hi,
>>>
>>> One more syntax proposal that extends P1985's unkiversal template
>>> parameter: `template auto`
>>>
>>> 1. allow `template auto` in any deduced context, for example
>>> `vector<template auto> vec = get_vec();`
>>> 2. use the syntax `template<class T> auto` to introduce the name `T`.
>>>
>>
>> Again, syntax. How on earth do you parse this? `template auto` in P1985's
>> usage is fine, since it's just alternate for *template-parameter* (or
>> *type-parameter*), with an alternation on the token `template` with
>> *template-head* resolved immediately at the next token (`auto` vs. `<`).
>> `vector<auto>` is similarly fine, since `auto` is already a
>> *simple-type-specifier*, so that's just a semantic relaxation.
>>
>> template<class T> auto x = foo()
>>> vector<template<class V> auto> v = get_vec()
>>>
>>> Some extra stuff:
>>> * Introducing a name is optional, you can use `template<class> auto` for
>>> a type placeholder, instead of a universal one
>>> * you can have nttp or template placeholders too
>>>
>>> std::array<string, template<size_t arr_size> auto> arr = get_arr();
>>>
>>> A bit verbose compared to my previously proposed auto<class T>.
>>> Honestly, I like that more, but I could live with this.
>>>
>>> I definitely wouldn't want a syntax where you are required to
>>> immediately repeat the introduced name.
>>>
>>
>> Repeating the name means that you can specify its kind (type, class
>> template, value, etc.) and easily see which names are introduced into scope.
>>
>> I really don't see the necessity to golf everything; C++ is already
>> notoriously hard to parse and you want to make it even harder?
>>
>>
>>> Cheers,
>>> Lénárd
>>>
>>> On 30 September 2022 15:01:58 BST, Edward Catmur via Std-Proposals <
>>> std-proposals_at_[hidden]> wrote:
>>>>
>>>>
>>>>
>>>> On Fri, 30 Sept 2022 at 14:19, Oleksandr Koval <
>>>> oleksandr.koval.dev_at_[hidden]> wrote:
>>>>
>>>>> Sorry if this was already discussed, I like `auto<class T>` syntax but
>>>>> the problem I see is this:
>>>>>
>>>>> std::vector<int> f();
>>>>> auto<class T> v = f(); // should T be `std::vector<int>` or just `int`?
>>>>>
>>>>
>>>> That syntax would work as a 2-step process: first you declare entities,
>>>> then deduce them. The declaration and deduction should be pretty much the
>>>> same as for (non-terse) function templates.
>>>>
>>>> So T is repeated:
>>>>
>>>> auto<class T> T v = f();
>>>>
>>>> or
>>>>
>>>> auto<class T> std::vector<T> v = f();
>>>>
>>>> or
>>>>
>>>> auto<template<class> class TT, class T> TT<T> v = f();
>>>>
>>>>
>>>> It’s a bit confusing when you see them side by side. Because of that I
>>>>> don’t think that using angle brackets is a good idea (at least I can’t find
>>>>> any form which is not confusing). We need a new syntax which will clearly
>>>>> show that typename(s) is closely related to `auto` itself. For example:
>>>>>
>>>>> auto:[class T] v = f();
>>>>> auto:[class T1, classT2] [key, value] = get_pair();
>>>>>
>>>>> On Fri, Sep 30, 2022 at 4:07 AM Edward Catmur via Std-Proposals <
>>>>> std-proposals_at_[hidden]> wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> On Thu, 29 Sept 2022 at 21:44, Arthur O'Dwyer <
>>>>>> arthur.j.odwyer_at_[hidden]> wrote:
>>>>>>
>>>>>>> On Thu, Sep 29, 2022 at 3:57 PM Lénárd Szolnoki via Std-Proposals <
>>>>>>> std-proposals_at_[hidden]> wrote:
>>>>>>>
>>>>>>>> On 29 September 2022 20:25:06 BST, Edward Catmur <
>>>>>>>> ecatmur_at_[hidden]> wrote:
>>>>>>>> >On Thu, 29 Sept 2022 at 18:15, Lénárd Szolnoki via Std-Proposals <
>>>>>>>> std-proposals_at_[hidden]> wrote:
>>>>>>>> >
>>>>>>>> >> I think this could be addressed by two distinct proposals.
>>>>>>>> >>
>>>>>>>> >> 1. allow placeholders to appear in any deduced context
>>>>>>>> (std::vector<auto>)
>>>>>>>> >> 2. allow a placeholder to introduce a name (auto<class T>,
>>>>>>>> auto<int i>
>>>>>>>> >> might appear as a deduced nttp)
>>>>>>>> >>
>>>>>>>> >> Then you can have your vector<auto<class T>> to deduce the value
>>>>>>>> type and
>>>>>>>> >> introduce the name T for that.
>>>>>>>> >
>>>>>>>> >std::vector<auto> is problematic, because elsewhere auto means a
>>>>>>>> value of
>>>>>>>> >unconstrained type (e.g. in template<auto>).
>>>>>>>>
>>>>>>>> I disagree. auto is a placeholder for the type of the non-type
>>>>>>>> parameter. If you don't omit the name, then that name refers to the value.
>>>>>>>>
>>>>>>>
>>>>>>> FWIW, I tend to agree with Lénárd here: `auto *p,
>>>>>>> std::unique_ptr<auto> q` seems quite reasonable to me.
>>>>>>>
>>>>>>
>>>>>> Ye-esss; looking at the grammar; `auto` is always a
>>>>>> placeholder-type-specifier, which is a simple-type-specifier, so it makes
>>>>>> sense that it takes the place of a concrete (or inferred) type.
>>>>>>
>>>>>> So Lénárd, I apologise; you're correct that in these contexts `auto`
>>>>>> designates a type, not a value. I'm still trying to get my head round
>>>>>> "template<auto> int f();", but the syntax is clear.
>>>>>>
>>>>>> *However*, I foresee practical problems with allowing auto *anywhere*
>>>>>>> in a declaration. Consider
>>>>>>> template<class T> void f(T t); // since C++98
>>>>>>> template<class T> void g(decltype(T(1)) t); // since C++11
>>>>>>> void f(auto t); // since C++20, equivalent to f #1
>>>>>>> void g(decltype(auto(1)) t); // since C++23, *not* equivalent
>>>>>>> to g #1
>>>>>>>
>>>>>>> Now, the `T` parameter to `g` is not deducible, so "obviously" the
>>>>>>> `auto` in g #2 doesn't mean the same thing as the `auto` in f #2. But are
>>>>>>> you sure we can teach that to the computer?
>>>>>>>
>>>>>>> (Background: I teach that `auto` since C++14 has (like most C++
>>>>>>> keywords) had two meanings: concrete type *inference*, as in auto x
>>>>>>> = 1, and templatey type *deduction*, as in [](auto x){}. The
>>>>>>> physical mechanisms behind, and consequences of, these two usages of `auto`
>>>>>>> are vastly different, although their human-level meaning is similar: "I
>>>>>>> don't want to bother with types; compiler, please figure it out." So if you
>>>>>>> see me talking about "inference" versus "deduction," or "the first meaning
>>>>>>> of auto" versus "the second meaning of auto," that's what I'm talking
>>>>>>> about.)
>>>>>>>
>>>>>>
>>>>>> The deduction process is ultimately the same; both end up in
>>>>>> temp.deduct.call. In an abbreviated function template or generic lambda,
>>>>>> the deduction can be overridden by explicit template argument, but that's a
>>>>>> relatively minor effect. And syntactically, they're the same; a
>>>>>> decl-specifier of a decl-specifier-seq (of a function parameter or variable
>>>>>> declaration); `auto` in a function return type or trailing return type has
>>>>>> less in common, though I'd suppose you'd class that as inference. Still, I
>>>>>> guess it's OK to teach it that way.
>>>>>>
>>>>>> It would certainly *not* be reasonable to have a rule like "Try to
>>>>>>> interpret every `auto` as deduction, but if that would result in a
>>>>>>> non-deducible template parameter, then backtrack and assume it's inference
>>>>>>> instead." It would be reasonable to have a rule that boils down to "Inside
>>>>>>> the operand of a decltype or sizeof or array bound, the `auto` always means
>>>>>>> inference not deduction." But is `g` above the *only* problem
>>>>>>> case? Are there other corner cases where `auto` is already legal today,
>>>>>>> and/or we wouldn't want it to mean a template parameter?
>>>>>>> void f(A<auto(int())>); // is this concrete A<0> or templatey
>>>>>>> A<T(int())>? I guess the type of A will disambiguate...
>>>>>>>
>>>>>>
>>>>>> Currently a placeholder can appear as the decl-specifier of a
>>>>>> function parameter, variable declaration, or template parameter or, as
>>>>>> exactly one simple-type-specifier of a return or trailing return type,
>>>>>> conversion function id, new expression's type id, or (`auto` only) as the
>>>>>> type specifier of a functional cast. If these were relaxed, I think we'd
>>>>>> probably be OK; you just go through inventing extra type template
>>>>>> parameters and perform deduction as usual.
>>>>>>
>>>>>> Also I don't think ambiguity *can* be an issue, or it would be
>>>>>> already; there must be disambiguators in the syntax. Indeed, I have a
>>>>>> strong suspicion that your `A<auto(int())>` is a most vexing parse.
>>>>>>
>>>>>> Also consider that while
>>>>>>> void h1(std::vector<auto, auto> v);
>>>>>>> would work fine with Lénárd's proposed syntax,
>>>>>>> void h2(std::array<auto, ??> a);
>>>>>>> would not. That does seem mildly problematic. However, maybe it's
>>>>>>> consistent with C++20, which permits
>>>>>>> template<class T> concept Integral = true;
>>>>>>> template<Integral T> void ij(); // since C++20
>>>>>>> but not
>>>>>>> template<int N> concept Odd = true;
>>>>>>> template<Odd N> void ij(); // error: Odd does not constrain a
>>>>>>> type
>>>>>>>
>>>>>>
>>>>>> Yes, fair enough; this does conform to the grammar.
>>>>>> --
>>>>>> Std-Proposals mailing list
>>>>>> Std-Proposals_at_[hidden]
>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Regards,
>>>>> Oleksandr Koval.
>>>>>
>>>> --
>>> Std-Proposals mailing list
>>> Std-Proposals_at_[hidden]
>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
>
> --
> Regards,
> Oleksandr Koval.
>
Received on 2022-10-17 16:55:33