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. 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.A synonym for class in template parameters
In C++'s generic programming feature known as "templates", typename can be used for introducing a template parameter: // Define a generic function that returns the greater of its two arguments
template
nodiscard
const T& max noexcept
An alternative and semantically equivalent keyword in this scenario is "
class":// Define a generic function that returns the greater of its two arguments
template
nodiscard
const T& max noexcept
When using concepts, a means of constraining the generic type to satisfy some set of rules, the name of the concept replaces the keyword
typename.import std;
using std::is_base_of_v;
using std::vector;
class Player ;
template
concept ExtendsPlayer = is_base_of_v
// T is required to be a type whose inheritance upper bound is Player,
// blocking any type that does not inherit from Player
template
void processListOfPlayers
A method for indicating that a dependent name is a type
Consider this invalid code:template
void foo
struct UsesBar ;
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 lineT::Bar* p;
will instead multiply the "value"
T::Bar by p and throw away the result. The fact that in UsesBar the dependent Bar is in fact a type does not help since foo could be compiled long before UsesBar is seen. Furthermore, if there is also a class like:struct HoldsBar ;
then the compiler would be obliged to interpret the
T::Bar in foo as an access to data member HoldsBar::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:template
void foo
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.