In templates, where and why do I have to put typename
and template
on dependent names? What exactly are dependent names anyway? I have the following code:
template <typename T, typename Tail> // Tail will be a UnionNode too.
struct UnionNode : public Tail {
// ...
template<typename U> struct inUnion {
// Q: where to add typename/template 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 {
char fail[ -2 + (sizeof(U)%2) ]; // Cannot be instantiated for any U
};
template< > struct inUnion<T> {
};
};
The problem I have is in the typedef Tail::inUnion<U> dummy
line. I'm fairly certain that inUnion
is a dependent name, and VC++ is quite right in choking on it. I also know that I should be able to add template
somewhere to tell the compiler that inUnion is a template-id. But where exactly? And should it then assume that inUnion is a class template, i.e. inUnion<U>
names a type and not a function?
In order to parse a C++ program, the compiler needs to know whether certain names are types or not. The following example demonstrates that:
How should this be parsed? For many languages a compiler doesn't need to know the meaning of a name in order to parse and basically know what action a line of code does. In C++, the above however can yield vastly different interpretations depending on what
t
means. If it's a type, then it will be a declaration of a pointerf
. However if it's not a type, it will be a multiplication. So the C++ Standard says at paragraph (3/7):How will the compiler find out what a name
t::x
refers to, ift
refers to a template type parameter?x
could be a static int data member that could be multiplied or could equally well be a nested class or typedef that could yield to a declaration. If a name has this property - that it can't be looked up until the actual template arguments are known - then it's called a dependent name (it "depends" on the template parameters).You might recommend to just wait till the user instantiates the template:
This will work and actually is allowed by the Standard as a possible implementation approach. These compilers basically copy the template's text into an internal buffer, and only when an instantiation is needed, they parse the template and possibly detect errors in the definition. But instead of bothering the template's users (poor colleagues!) with errors made by a template's author, other implementations choose to check templates early on and give errors in the definition as soon as possible, before an instantiation even takes place.
So there has to be a way to tell the compiler that certain names are types and that certain names aren't.
The "typename" keyword
The answer is: We decide how the compiler should parse this. If
t::x
is a dependent name, then we need to prefix it bytypename
to tell the compiler to parse it in a certain way. The Standard says at (14.6/2):There are many names for which
typename
is not necessary, because the compiler can, with the applicable name lookup in the template definition, figure out how to parse a construct itself - for example withT *f;
, whenT
is a type template parameter. But fort::x * f;
to be a declaration, it must be written astypename t::x *f;
. If you omit the keyword and the name is taken to be a non-type, but when instantiation finds it denotes a type, the usual error messages are emitted by the compiler. Sometimes, the error consequently is given at definition time:The syntax allows
typename
only before qualified names - it is therefor taken as granted that unqualified names are always known to refer to types if they do so.A similar gotcha exists for names that denote templates, as hinted at by the introductory text.
The "template" keyword
Remember the initial quote above and how the Standard requires special handling for templates as well? Let's take the following innocent-looking example:
It might look obvious to a human reader. Not so for the compiler. Imagine the following arbitrary definition of
boost::function
andf
:That's actually a valid expression! It uses the less-than operator to compare
boost::function
against zero (int()
), and then uses the greater-than operator to compare the resultingbool
againstf
. However as you might well know,boost::function
in real life is a template, so the compiler knows (14.2/3):Now we are back to the same problem as with
typename
. What if we can't know yet whether the name is a template when parsing the code? We will need to inserttemplate
immediately before the template name, as specified by14.2/4
. This looks like:Template names can not only occur after a
::
but also after a->
or.
in a class member access. You need to insert the keyword there too:Dependencies
For the people that have thick Standardese books on their shelf and that want to know what exactly I was talking about, I'll talk a bit about how this is specified in the Standard.
In template declarations some constructs have different meanings depending on what template arguments you use to instantiate the template: Expressions may have different types or values, variables may have different types or function calls might end up calling different functions. Such constructs are generally said to depend on template parameters.
The Standard defines precisely the rules by whether a construct is dependent or not. It separates them into logically different groups: One catches types, another catches expressions. Expressions may depend by their value and/or their type. So we have, with typical examples appended:
T
)N
)(T)0
)Most of the rules are intuitive and are built up recursively: For example, a type constructed as
T[N]
is a dependent type ifN
is a value-dependent expression orT
is a dependent type. The details of this can be read in section(14.6.2/1
) for dependent types,(14.6.2.2)
for type-dependent expressions and(14.6.2.3)
for value-dependent expressions.Dependent names
The Standard is a bit unclear about what exactly is a dependent name. On a simple read (you know, the principle of least surprise), all it defines as a dependent name is the special case for function names below. But since clearly
T::x
also needs to be looked up in the instantiation context, it also needs to be a dependent name (fortunately, as of mid C++14 the committee has started to look into how to fix this confusing definition).To avoid this problem, I have resorted to a simple interpretation of the Standard text. Of all the constructs that denote dependent types or expressions, a subset of them represent names. Those names are therefore "dependent names". A name can take different forms - the Standard says:
An identifier is just a plain sequence of characters / digits, while the next two are the
operator +
andoperator type
form. The last form istemplate-name <argument list>
. All these are names, and by conventional use in the Standard, a name can also include qualifiers that say what namespace or class a name should be looked up in.A value dependent expression
1 + N
is not a name, butN
is. The subset of all dependent constructs that are names is called dependent name. Function names, however, may have different meaning in different instantiations of a template, but unfortunately are not caught by this general rule.Dependent function names
Not primarily a concern of this article, but still worth mentioning: Function names are an exception that are handled separately. An identifier function name is dependent not by itself, but by the type dependent argument expressions used in a call. In the example
f((T)0)
,f
is a dependent name. In the Standard, this is specified at(14.6.2/1)
.Additional notes and examples
In enough cases we need both of
typename
andtemplate
. Your code should look like the followingThe keyword
template
doesn't always have to appear in the last part of a name. It can appear in the middle before a class name that's used as a scope, like in the following exampleIn some cases, the keywords are forbidden, as detailed below
On the name of a dependent base class you are not allowed to write
typename
. It's assumed that the name given is a class type name. This is true for both names in the base-class list and the constructor initializer list:In using-declarations it's not possible to use
template
after the last::
, and the C++ committee said not to work on a solution.I am placing JLBorges's excellent response to a similar question verbatim from cplusplus.com, as it is the most succinct explanation I've read on the subject.
Summary
Use the keyword typename only in template declarations and definitions provided you have a qualified name that refers to a type and depends on a template parameter.
However, I'm not sure you're implementation of inUnion is correct. If I understand correctly, this class is not supposed to be instantiated, therefore the "fail" tab will never avtually fails. Maybe it would be better to indicates whether the type is in the union or not with a simple boolean value.
PS: Have a look at Boost::Variant
PS2: Have a look at typelists, notably in Andrei Alexandrescu's book: Modern C++ Design
C++11
Problem
While the rules in C++03 about when you need
typename
andtemplate
are largely reasonable, there is one annoying disadvantage of its formulationAs can be seen, we need the disambiguation keyword even if the compiler could perfectly figure out itself that
A::result_type
can only beint
(and is hence a type), andthis->g
can only be the member templateg
declared later (even ifA
is explicitly specialized somewhere, that would not affect the code within that template, so its meaning cannot be affected by a later specialization ofA
!).Current instantiation
To improve the situation, in C++11 the language tracks when a type refers to the enclosing template. To know that, the type must have been formed by using a certain form of name, which is its own name (in the above,
A
,A<T>
,::A<T>
). A type referenced by such a name is known to be the current instantiation. There may be multiple types that are all the current instantiation if the type from which the name is formed is a member/nested class (then,A::NestedClass
andA
are both current instantiations).Based on this notion, the language says that
CurrentInstantiation::Foo
,Foo
andCurrentInstantiationTyped->Foo
(such asA *a = this; a->Foo
) are all member of the current instantiation if they are found to be members of a class that is the current instantiation or one of its non-dependent base classes (by just doing the name lookup immediately).The keywords
typename
andtemplate
are now not required anymore if the qualifier is a member of the current instantiation. A keypoint here to remember is thatA<T>
is still a type-dependent name (after allT
is also type dependent). ButA<T>::result_type
is known to be a type - the compiler will "magically" look into this kind of dependent types to figure this out.That's impressive, but can we do better? The language even goes further and requires that an implementation again looks up
D::result_type
when instantiatingD::f
(even if it found its meaning already at definition time). When now the lookup result differs or results in ambiguity, the program is ill-formed and a diagnostic must be given. Imagine what happens if we definedC
like thisA compiler is required to catch the error when instantiating
D<int>::f
. So you get the best of the two worlds: "Delayed" lookup protecting you if you could get in trouble with dependent base classes, and also "Immediate" lookup that frees you fromtypename
andtemplate
.Unknown specializations
In the code of
D
, the nametypename D::questionable_type
is not a member of the current instantiation. Instead the language marks it as a member of an unknown specialization. In particular, this is always the case when you are doingDependentTypeName::Foo
orDependentTypedName->Foo
and either the dependent type is not the current instantiation (in which case the compiler can give up and say "we will look later whatFoo
is) or it is the current instantiation and the name was not found in it or its non-dependent base classes and there are also dependent base classes.Imagine what happens if we had a member function
h
within the above definedA
class templateIn C++03, the language allowed to catch this error because there could never be a valid way to instantiate
A<T>::h
(whatever argument you give toT
). In C++11, the language now has a further check to give more reason for compilers to implement this rule. SinceA
has no dependent base classes, andA
declares no memberquestionable_type
, the nameA<T>::questionable_type
is neither a member of the current instantiation nor a member of an unknown specialization. In that case, there should be no way that that code could validly compile at instantiation time, so the language forbids a name where the qualifier is the current instantiation to be neither a member of an unknown specialization nor a member of the current instantiation (however, this violation is still not required to be diagnosed).Examples and trivia
You can try this knowledge on this answer and see whether the above definitions make sense for you on a real-world example (they are repeated slightly less detailed in that answer).
The C++11 rules make the following valid C++03 code ill-formed (which was not intended by the C++ committee, but will probably not be fixed)
This valid C++03 code would bind
this->f
toA::f
at instantiation time and everything is fine. C++11 however immediately binds it toB::f
and requires a double-check when instantiating, checking whether the lookup still matches. However when instantiatingC<A>::g
, the Dominance Rule applies and lookup will findA::f
instead.This answer is meant to be a rather short and sweet one to answer (part of) the titled question. If you want an answer with more detail that explains why you have to put them there, please go here.
The general rule for putting the
typename
keyword is mostly when you're using a template parameter and you want to access a nestedtypedef
or using-alias, for example:Note that this also applies for meta functions or things that take generic template parameters too. However, if the template parameter provided is an explicit type then you don't have to specify
typename
, for example:The general rules for adding the
template
qualifier are mostly similar except they typically involve templated member functions (static or otherwise) of a struct/class that is itself templated, for example:Given this struct and function:
Attempting to access
t.get<int>()
from inside the function will result in an error:Thus in this context you would need the
template
keyword beforehand and call it like so:t.template get<int>()
That way the compiler will parse this properly rather than
t.get < int
.What's the purpose of
typename
andtemplate
?typename
andtemplate
are usable in circumstances other than when declaring a template.There are certain contexts in C++ where the compiler must explicitly be told how to treat a name, and all these contexts have one thing in common; they depend on at least one template-parameter.
We refer to such names, where there can be an ambiguity in interpretation, as; "dependent names".
This post will offer an explanation to the relationship between dependent-names, and the two keywords.
A SNIPPET SAYS MORE THAN 1000 WORDS
Try to explain what is going on in the following function-template, either to yourself, a friend, or perhaps your cat; what is happening in the statement marked (A)?
It might not be as easy as one thinks, more specifically the result of evaluating (A) heavily depends on the definition of the type passed as template-parameter
T
.Different
T
s can drastically change the semantics involved.The two different scenarios:
If we instantiate the function-template with type X, as in (C), we will have a declaration of a pointer-to int named x, but;
if we instantiate the template with type Y, as in (D), (A) would instead consist of an expression that calculates the product of 123 multiplied with some already declared variable x.
THE RATIONALE
The C++ Standard cares about our safety and well-being, at least in this case.
To prevent an implementation from potentially suffering from nasty surprises, the Standard mandates that we sort out the ambiguity of a dependent-name by explicitly stating the intent anywhere we'd like to treat the name as either a type-name, or a template-id.
If nothing is stated, the dependent-name will be considered to be either a variable, or a function.
HOW TO HANDLE DEPENDENT NAMES?
If this was a Hollywood film, dependent-names would be the disease that spreads through body contact, instantly affects its host to make it confused. Confusion that could, possibly, lead to an ill-formed perso-, erhm.. program.
A dependent-name is any name that directly, or indirectly, depends on a template-parameter.
We have four dependent names in the above snippet:
SomeTrait<T>
, which includeT
, and;SomeTrait<T>
, and;SomeTrait<T>
, and;SomeTrait<T>
.Neither of statement (E), (F) or (G) is valid if the compiler would interpret the dependent-names as variables/functions (which as stated earlier is what happens if we don't explicitly say otherwise).
THE SOLUTION
To make
g_tmpl
have a valid definition we must explicitly tell the compiler that we expect a type in (E), a template-id and a type in (F), and a template-id in (G).Every time a name denotes a type, all names involved must be either type-names or namespaces, with this in mind it's quite easy to see that we apply
typename
at the beginning of our fully qualified name.template
however, is different in this regard, since there's no way of coming to a conclusion such as; "oh, this is a template, then this other thing must also be a template". This means that we applytemplate
directly in front of any name that we'd like to treat as such.CAN I JUST STICK THE KEYWORDS IN FRONT OF ANY NAME?
The rules in the Standard states that you may apply the keywords as long as you are dealing with a qualified-name (K), but if the name isn't qualified the application is ill-formed (L).
Note: Applying
typename
ortemplate
in a context where it is not required is not considered good practice; just because you can do something, doesn't mean that you should.Additionally there are contexts where
typename
andtemplate
are explicitly disallowed:When specifying the bases of which a class inherits
Every name written in a derived class's base-specifier-list is already treated as a type-name, explicitly specifying
typename
is both ill-formed, and redundant.When the template-id is the one being referred to in a derived class's using-directive