Why don't I need to specify "typename" before a dependent type in C++20?

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.

One such context is the return type of a function in class scope, as in your example. Others include the type in a member declaration, the type on the right-hand side of a using declaration, the parameter declaration of a lambda, the type you're passing to static_cast, etc. See the paper for the full list.


Nearly all because base-specifiers and mem-initializer-ids were always excluded, as in:

template <typename T> struct X : T::type  { }; // always ok

This is okay because, well, that needs to be a type. The paper simply extends this logic (well, it has to be a type, so let's just assume it's a type) to a lot more places that have to be types.


From the reference, from c++20, in contexts where the dependent name is unambiguously a typename, the typename keyword is no longer needed. In particular:

A qualified name that is used as a declaration specifier in the (top-level) decl-specifier-seq of:

a simple declaration or function definition at namespace scope