"typename
"[1] [2] 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. In the original C++ compilers before the first ISO standard was completed, the typename
keyword was not part of the C++ language and Bjarne Stroustrup used the class
keyword for template arguments instead. While typename
is now the preferred keyword, older source code may still use the class
keyword instead (for example see the difference in source code examples between The Design and Evolution of C++ by Bjarne Stroustrup published in 1994 and the source code examples in The C++ Programming Language: Fourth Edition by Bjarne Stroustrup published in 2013).
class
" in template parametersIn C++'s generic programming feature known as "templates", typename
can be used for introducing a template parameter:[3] [4]
An alternative and semantically equivalent keyword in this scenario is "class
":
Consider this invalid code:[5]
struct StructWithBarAsType
int main
This code looks like it should compile, but it is incorrect because the compiler does not know if T::bar
is a type or a value. The reason it doesn't know is that T::bar
is a "template-parameter dependent name", or "dependent name" for short, which then could represent anything named "bar" inside a type passed to foo, which could include typedefs, enums, variables, etc.
To resolve this ambiguity, the C++ Language Standard declares:
A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename
.
In short, if the compiler can't tell if a dependent name is a value or a type, then it will assume that it is a value. In our example, where T::bar
is the dependent name, that means that rather than declaring a pointer to T::bar
named p
, the line T::bar * p;will instead multiply the "value" T::bar
by p
(which is nowhere to be found) and throw away the result. The fact that in StructWithBarAsType
the dependent bar
is in fact a type does not help since foo
could be compiled long before StructWithBarAsType
is seen. Furthermore, if there is also a class like:
T::bar
in foo
as an access to data member StructWithBarAsValue::bar
when instantiated. But since bar
is not a static data member it will flag an error.The solution to this problem is to explicitly tell the compiler that T::bar
is in fact a type. For this, the typename
keyword is used:[3] [4]
Now the compiler knows for sure that T::bar
is a type, and will correctly make p
a pointer to an object of that type.