I’m sure typename and typedef are not new to anyone who has used C++, but I still couldn’t understand the following code when I saw it.
It stands to reason that typedef is not generally used to define an alias for a type, as follows.
Having defined an int with the alias SpeedType, I can then use it like this.
But what does typedef followed by typename mean, and isn’t typename used to define template parameters? Let’s summarize the usage of typedef & typename separately.
First, let’s look at a few common uses of typedef.
Aliases for types with specific meanings
I’ve already covered this above, but it’s defining an alias for a type, not just a simple macro substitution, and can also be used to declare multiple objects of the pointer type at the same time.
We wanted to declare both pa and pb as strings, but we could only declare one of them successfully.
But we can declare both of them using typedef.
When declaring variables, you need to bring struct, i.e. use it like the following.
Used to define platform-independent types
For example, define a floating point type called REAL, on target platform 1, and let it represent the highest precision type as follows.
On platform 2, which does not support long double, it is modified as follows.
When cross-platform, just change the typedef itself, without making any changes to the rest of the source code.
The typename keyword is used to introduce a template parameter. This keyword is used to indicate that the non-dependent names in the template declaration (or definition) are type names, not variable names.
typename in this context means that T is a type. Without it, ambiguity can arise in some cases, such as the following.
The author wants to define a pointer
iter that points to an
iterator of type contained in the class scope
T. It is possible that there is such a structure containing the type
foo<ContainsAType>(); when used this way does tell
iter is a pointer of type
T::iterator can actually be of any of the following three types.
- Static data members
- Static member functions
- Nested types
So if it is a case like the following.
T::iterator * iter; is instantiated by the compiler as
ContainsAnotherType::iterator * iter; and becomes a static data member multiplied by iter, so that the compiler will not find the definition of another variable
iter. So to avoid this ambiguity, we add typename to indicate that
T::iterator must be a type.
Let’s go back to the example at the beginning, for
vector::size_type, we can know that
vector::size_type is a nested type definition of
vector, which is actually equivalent to the
The real face of this example, then, is that
typedef creates an alias for the existent type, and
typename tells the compiler that
std::vector<T>::size_type is a type and not a member.
Well, after reading the above example you should have fully understood the essence of typedef & typename, let’s explain an example of using a template to implement a loop similar to the one below.
First we need a loop template.
As you can see here, the templates, both res_type and type, are modified with typename to indicate that they are types, and then typedef to indicate that an alias is defined for the type.
When defining the loop template again, there is a convention that it must provide a static data member, cond_value, and two subtype definitions, res_type and next_type.
- cond_value represents the condition of the loop (true or false), indicating that it is directly a static data member of definite bool type, unmodified by typename.
- res_type represents the state when the loop is exited, and is a type rather than a member.
- next_type represents the state when the following loop is executed once, and is a type rather than a member.
WhileLoop uses specialization to decide whether to take the recursive branch or exit the loop branch.
We then define a template to represent the value.
The value can be obtained by value, and the value_type is the type of the value.
The above template enables the result of
While<Sum<10>::type>::type::value 1 to 10. In fact, the result of the 1 to 10 operation is achieved by a circular expansion of types.