template<class T>
T::type<int> f(){
}
According to [temp.names#3.4]
A < is interpreted as the delimiter of a template-argument-list if it follows a name that is not a conversion-function-id and
- [...]
- that is a terminal name in a using-declarator ([namespace.udecl]), in a declarator-id ([dcl.meaning]), or in a type-only context other than a nested-name-specifier ([temp.res]).
According to [temp.res#general-4.3.1], T::type<int>
does satisfy the above rule(emphasized mine) due to the following rule
A qualified or unqualified name is said to be in a type-only context if it is the terminal name of
- [...]
- a decl-specifier of the decl-specifier-seq of a
- [...]
- simple-declaration or a function-definition in namespace scope,
T::type<int>
is the decl-specifier of the function-definition for template function f
that is in the namespace scope, hence the terminal name type
is said to be in the type-only context.
Also, according to [temp.res#general-5]
A qualified-id whose terminal name is dependent and that is in a type-only context is considered to denote a type.
Hence, the symbol <
in T::type<int>
is interpreted as the delimiter of the template-argument-list due to [temp.names#3.4] while the qualified-id T::type<int>
is considered to denote a type due to [temp.res#general-5], the example should be legal. However, it has been rejected by both Clang and GCC.
I wonder, Are both the keyword typename
and template
not necessary in this example compiled by future implementations?
The typename keyword is needed whenever a type name depends on a template parameter, (so the compiler can 'know' the semantics of an identifier (type or value) without having a full symbol table at the first pass).
typename is needed in your declaration of 'it' because otherwise the compiler doesn't know that it's a type declaration rather than an expression. According to this page, "Use the keyword typename if you have a qualified name that refers to a type and depends on a template parameter."
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
Yes, this is the rule, and it’s correct; compilers simply haven’t implemented the (newer) template
part yet. In discussing that addition, an example was brought up that illustrates the absurdity of requiring the keyword in this context:
template<typename T> struct A {
template<typename U> struct B {
B();
};
template<typename U> B<U> make();
};
template<typename T> template<typename U>
A<T>::B<U>::B() {} // no 'template' keyword required before 'B' here, but...
template<typename T> template<typename U>
A<T>::B<U> A<T>::make() { return {}; } // 'template' keyword required before 'B' here?
This also illustrates part of the motivation for dropping the requirement for typename
in many contexts. A<T>::B
might be a dependent name (if the declaration ends up being for something that’s not a member of (the primary template of) A
), but that doesn’t interfere with parsing it since no expression can appear there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With