According to https://stackoverflow.com/a/61991146/508343:
One of the new features in C++20 is Down with typename.
In C++17, you had to provide the typename keyword in nearly all† dependent contexts to disambiguate a type from a value. But in C++20, this rule is relaxed a lot. In all contexts where you need to have a type, the typename keyword is no longer mandatory.
template<typename T>
concept IsOK = true;
template<typename T>
requires IsOK<T::U> // error: use ‘typename T::U’
void f()
{}
struct A
{
using U = int;
};
int main()
{
f<A>();
}
In the code above, obviously, IsOK
concept can take types only.
Why is typename
required here?
See online demo
The answer is speaking loosely about what "context" means. What the feature is doing is finding places where it is grammatically impossible for anything other than a typename to appear in that location. It is those places where typename
is no longer necessary.
For example, using name = X;
. Grammatically, this is a type alias declaration. As such, whatever X
is, the grammar requires that it be a type. If the X
happens to be a name dependent on a template parameter, whatever that name is must be a type. So the grammar is unambiguous, and typename
is redundant.
The syntax name<X>
states that X
is a template argument to the template name
. But template arguments do not have to be types. A specific template may take a type as a specific argument, but grammatically, X
could be an identifier referencing a variable or a template. Therefore, you must disambiguate ambiguous dependent X
s.