Question
Dependent Names, typename, and template in C++ Templates
Question
In C++ templates, when and why do you need to write typename and template for dependent names?
What exactly is a dependent name?
For example, consider this code:
template <typename T, typename Tail> // Tail will also be a UnionNode.
struct UnionNode : public Tail {
template <typename U>
struct inUnion {
// Where should typename/template be added here?
typedef Tail::inUnion<U> dummy;
};
template <>
struct inUnion<T> { };
};
template <typename T> // For the last node Tn.
struct UnionNode<T, void> {
template <typename U>
struct inUnion; // intentionally not defined
template <>
struct inUnion<T> { };
};
The issue is with this line:
typedef Tail::inUnion<U> dummy;
It seems that inUnion is a dependent name, so the compiler cannot know immediately what it refers to. I understand that template can be used to tell the compiler that inUnion is a template, but where exactly should it go?
Also, if template is used, does that automatically mean inUnion<U> is treated as a type rather than a function or something else?
Short Answer
By the end of this page, you will understand what dependent names are in C++, why the compiler sometimes needs extra help inside templates, and exactly when to use the typename and template keywords. You will also see how to fix expressions like Tail::inUnion<U> correctly and learn the common rules developers use in real template code.
Concept
In C++, templates are parsed in two phases:
- Phase 1: the compiler parses the template before knowing the actual template arguments.
- Phase 2: the compiler instantiates the template later, when real types are substituted.
Because of this, some names inside a template depend on a template parameter and cannot be fully understood during the first phase. These are called dependent names.
A name is dependent if its meaning depends on a template parameter. For example:
Tail::inUnion<U>
Here, Tail is a template parameter, so the compiler does not yet know what members Tail has. That means:
- it does not know whether
inUnionis a type, function, variable, or template - it cannot safely parse
<U>as template arguments unless you tell it to
This is why C++ provides two disambiguation keywords:
typenametells the compiler: this dependent qualified name is a typetemplatetells the compiler: this dependent qualified name is a template
For your example, the correct form is:
typedef typename Tail::template inUnion<U> dummy;
Why both?
Tail::...is dependent becauseTailis unknown at first parse time.inUnionis a member template, so the compiler needstemplatebeforeinUnion<U>.- The whole
Tail::template inUnion<U>names a type, sotypenameis also required.
This matters in real programming because template-heavy C++ code often uses nested types, member templates, iterators, traits, allocators, policy classes, and metaprogramming utilities. Understanding these rules makes template code readable, correct, and portable across compilers.
Mental Model
Think of the compiler as reading a sentence with missing dictionary entries.
If it sees this:
Tail::inUnion<U>
it thinks:
- “I do not know what
Tailis yet.” - “So I do not know what
inUnionmeans here.” - “That
<U>might be template arguments... or it might be a less-than operator.” - “I also do not know whether the whole thing is a type.”
So you must label it clearly:
template= “parse the following name as a template”typename= “treat the result as a type”
A simple analogy:
templateis like saying: this is a generic blueprinttypenameis like saying: the thing produced here is a type name
Without those labels, the compiler refuses to guess in dependent contexts.
Syntax and Examples
Core rule
When you refer to a member template through a dependent type, write:
typename DependentType::template MemberTemplate<Args...>
When you refer to a nested type through a dependent type, write:
typename DependentType::NestedType
Your example fixed
template <typename T, typename Tail>
struct UnionNode : public Tail {
template <typename U>
struct inUnion {
typedef typename Tail::template inUnion<U> dummy;
};
};
This says:
Tail::...depends onTailinUnionis a templateinUnion<U>is a type
Example: dependent nested type
template <typename Container>
void printFirst(const Container& c) {
typename Container::value_type x = *c.begin();
}
Why typename?
Because Container::value_type depends on Container, and the compiler does not know yet that value_type is a type.
Example: dependent member template call
template <typename T>
struct Wrapper {
template <typename U>
struct Rebind {
using type = U;
};
};
template <typename X>
void example() {
typename X::template Rebind<int>::type value = 42;
}
Here:
X::template Rebind<int>usestemplatebecauseRebindis a member template of dependent typeXtypenameis needed becauseX::template Rebind<int>::typeis a dependent type
Important note
Using template does not automatically mean the final expression is a type.
For example:
obj.template func<int>();
This uses template because func is a dependent member template, but this is a function call, not a type.
So:
templatemeans “this name is a template”typenamemeans “this dependent qualified expression names a type”
Step by Step Execution
Consider this example:
template <typename Tail>
struct Node {
template <typename U>
struct inner {
using type = U;
};
template <typename U>
void test() {
typename Tail::template inner<U> value;
}
};
Step-by-step
- The compiler starts parsing
Node<Tail>. - It sees
Tail::template inner<U>insidetest(). Tailis a template parameter, so the compiler does not know its real type yet.- Therefore,
Tail::inneris a dependent name. - Without help, the compiler cannot know whether
inneris:- a type
- a static member
- a function
- a template
- The
templatekeyword tells the compiler thatinneris a template. - The
typenamekeyword tells the compiler thatTail::template inner<U>names a type. - Now the declaration is valid.
What happens if you omit them?
Broken version:
template <typename Tail>
struct Node {
template <typename U>
void test() {
Tail::inner<U> value;
}
};
Problems:
- the compiler may not parse
<U>as template arguments - it does not know whether
Tail::inner<U>is a type
Correct version:
template <typename Tail>
struct Node {
template <typename U>
void test() {
typename Tail::template inner<U> value;
}
};
Real World Use Cases
Dependent names appear often in real C++ code, especially in generic libraries.
1. Standard-library style generic code
template <typename Container>
void process(const Container& c) {
typename Container::const_iterator it = c.begin();
}
Used when writing functions that work with many container types.
2. Traits and type transformations
template <typename Traits>
using value_type_t = typename Traits::value_type;
Common in type traits, allocators, iterators, and metaprogramming helpers.
3. Rebinding or nested templates
template <typename Alloc>
using int_alloc = typename Alloc::template rebind<int>::other;
Older allocator patterns and some generic libraries use this style.
4. CRTP and policy-based design
template <typename Policy>
struct Engine : Policy {
void run() {
typename Policy::config cfg;
}
};
Useful when behavior or configuration comes from template parameters.
5. Generic member template calls
template <typename T>
void call(T& obj) {
obj.template handle<int>();
}
This appears when a generic object has member templates and its concrete type is not known yet.
Real Codebase Usage
In real projects, developers usually encounter these rules in a few repeatable patterns.
Guarding dependent types with aliases
Instead of repeatedly writing long dependent names, developers often create aliases:
template <typename Tail>
struct Node {
template <typename U>
using inner_t = typename Tail::template inner<U>;
};
This improves readability and reduces mistakes.
Validation through traits
Template code often checks whether a nested type or member template exists:
template <typename T>
using value_type_t = typename T::value_type;
This is common in generic utilities and library internals.
Early clarification in complex declarations
When a declaration is hard to read, developers put the type into a using declaration first:
template <typename Tail>
struct Node {
template <typename U>
void f() {
using inner_type = typename Tail::template inner<U>;
inner_type x;
}
};
Error handling through clearer template structure
Compilers can produce confusing template errors. A common practice is to:
- break long dependent expressions into smaller aliases
- use
usinginstead of old-styletypedef - keep nested template references localized
Generic APIs and configuration types
Many libraries expose nested types such as:
value_typeiteratorconst_iteratortyperebind<U>
Whenever these are reached through a template parameter, typename and sometimes template are part of normal code.
Common Mistakes
1. Forgetting typename for a dependent type
Broken code:
template <typename T>
void f() {
T::value_type x;
}
Correct:
template <typename T>
void f() {
typename T::value_type x;
}
Why: T::value_type depends on T, so the compiler needs to be told that it is a type.
2. Forgetting template for a dependent member template
Broken code:
template <typename T>
void f() {
typename T::rebind<int>::other x;
}
Correct:
template <typename T>
void f() {
typename T::template rebind<int>::other x;
}
Why: rebind is a template member of dependent type T.
3. Thinking template implies typename
Broken assumption:
template <typename T>
void f() {
T::template rebind<int> x;
}
This may still need typename if the expression names a type:
template <typename T>
void f() {
typename T::template rebind<int> x;
}
template and typename solve different problems.
4. Using typename where it is not allowed or needed
Example:
template <typename T>
struct S : T::Base {
};
Base-class lists have their own parsing rules. You do not always write typename everywhere you see a dependent name.
A simpler rule for beginners:
- in declarations, if a dependent qualified name is a type, you usually need
typename - if it is also a template, you may need
templatetoo
5. Confusing type names with function calls
obj.template foo<int>();
This uses template, but not typename, because this is a function call, not a type declaration.
6. Blaming the wrong token
In code like this:
typedef Tail::inUnion<U> dummy;
both issues exist:
- the compiler does not know
inUnionis a template - the compiler does not know the full name is a type
So the fix is:
typedef typename Tail::template inUnion<U> dummy;
Comparisons
| Situation | Example | Need typename? | Need template? | Why |
|---|---|---|---|---|
| Dependent nested type | T::value_type | Yes | No | It is a type, but not a template |
| Dependent member template naming a type | T::rebind<int> | Yes | Yes | It is both a template and a type |
| Dependent member template function call | obj.foo<int>() | No | Yes, as obj.template foo<int>() | It is a template call, not a type |
| Non-dependent nested type | std::vector<int>::value_type | No | No | Compiler already knows what it is |
| Non-dependent class template | std::vector<int> | No | No | No ambiguity from a template parameter |
typename vs template
| Keyword | Purpose | Example |
|---|---|---|
typename | Says a dependent qualified name is a type | typename T::value_type |
template | Says a dependent qualified name is a template | T::template rebind<int> |
Old-style typedef vs using
| Style | Example | Notes |
|---|---|---|
typedef | typedef typename T::template rebind<int> type; | Works, but harder to read |
using | using type = typename T::template rebind<int>; | Usually clearer in modern C++ |
Cheat Sheet
Quick rules
- A dependent name is a name whose meaning depends on a template parameter.
- Use
typenamewhen a dependent qualified name refers to a type. - Use
templatewhen a dependent qualified name refers to a template. - Sometimes you need both.
Common patterns
typename T::value_type
typename T::template rebind<int>
obj.template func<int>()
Your case
typedef typename Tail::template inUnion<U> dummy;
Meaning of each keyword
typename=> “this is a type”template=> “this is a template”
When typename is not needed
- For non-dependent names
- In some special syntactic contexts
- For function calls like:
obj.template run<int>();
Safe beginner rule
If you see Something::Other inside a template and Something depends on a template parameter:
- If
Otheris a type, addtypename - If
Otheris a template used with<...>, addtemplate - If both are true, use both
Readability tip
Prefer using in modern C++:
using dummy = typename Tail::template inUnion<U>;
FAQ
What is a dependent name in C++?
A dependent name is a name whose meaning depends on a template parameter. For example, T::value_type depends on what T actually is.
Why does C++ need typename?
Because when parsing a template, the compiler cannot always know whether a dependent qualified name refers to a type. typename removes that ambiguity.
Why does C++ need the template keyword?
Because the compiler cannot always tell whether a dependent member name followed by <...> is a template or something else. template tells it to parse the name as a template.
Do I always need both typename and template?
No. You use:
- only
typenamefor dependent types that are not templates - only
templatefor dependent template function calls - both when a dependent member template names a type
What is the correct fix for Tail::inUnion<U>?
Use:
typedef typename Tail::template inUnion<U> dummy;
Or in modern C++:
using dummy = typename Tail::template inUnion<U>;
Does template mean the result is a type?
No. It only says the named member is a template. The result might be a type or a function call depending on context.
Why does some compiler code seem to work without these keywords?
Some compilers historically accepted missing keywords as extensions or had incomplete two-phase lookup behavior. Standard C++ requires the correct form.
Is typename used for all type names in templates?
No. It is specifically for dependent qualified names where the compiler cannot otherwise know the name is a type.
Mini Project
Description
Build a small type-traits-style utility that checks whether a container-like type provides a nested value_type and a nested member template rebind<U>. This project demonstrates both forms of disambiguation: using typename for dependent nested types and template for dependent member templates.
Goal
Create a C++ program that successfully accesses a dependent nested type and a dependent member template using the correct syntax.
Requirements
- Define a type with a nested
value_typealias. - Define a member template
rebind<U>inside that type. - Write a generic function or alias that accesses
value_typethrough a template parameter. - Write another generic alias that accesses
rebind<int>through a template parameter. - Compile and print a small result to prove the types were resolved correctly.
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.