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:
- Type template parameters are overwhelmingly more common than non-type or template template parameters.
- 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