Why don't I need to specify "typename" before a dependent type in C++20?
This bit of code compiled in C++20 (using gcc 10.1) without using the typename
keyword before the dependent type std::vector<T>::iterator
. Why does it compile?
#include <vector>
template<typename T>
std::vector<T>::iterator // Why does this not require "typename" before it?
f() { return {}; }
int main() {
auto fptr = &f<int>;
}
code playground
Solution 1:
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.
Solution 2:
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