patterncppCritical
Where and why do I have to put the "template" and "typename" keywords?
Viewed 0 times
keywordstypenamehavewhyandwherethetemplateput
Problem
In templates, where and why do I have to put
What exactly are dependent names anyway?
I have the following code:
The problem I have is in the
I also know that I should be able to add
typename and template on dependent names?What exactly are dependent names anyway?
I have the following code:
template // Tail will be a UnionNode too.
struct UnionNode : public Tail {
// ...
template struct inUnion {
// Q: where to add typename/template here?
typedef Tail::inUnion dummy;
};
template struct inUnion { };
};
template // For the last node Tn.
struct UnionNode {
// ...
template struct inUnion; // intentionally not defined
template struct inUnion { }; // specialization only for T
};The problem I have is in the
typedef Tail::inUnion 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? Should it then assume that inUnion is a class template, i.e. inUnion names a type and not a function?Solution
(See here also for my C++11 answer)
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
Some names denote types or templates. In general, whenever a name is encountered it is necessary to determine whether that name denotes one of these entities before continuing to parse the program that contains it. The process that determines this is called name lookup.
How will the compiler find out what a name
You might recommend to just wait till the user instantiates the template:
Let's wait until the user instantiates the template, and then later find out the real meaning of
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
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.
There are many names for which
The syntax allows
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
That's actually a valid expression! It uses the less-than operator to compare
After name lookup (3.4) finds that a name is a template-name, if this name is followed by a
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 hav
In order to parse a C++ program, the compiler needs to know whether certain names are types or not. The following example demonstrates that:
t * f;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 pointer f. However if it's not a type, it will be a multiplication. So the C++ Standard says at paragraph (3/7):Some names denote types or templates. In general, whenever a name is encountered it is necessary to determine whether that name denotes one of these entities before continuing to parse the program that contains it. The process that determines this is called name lookup.
How will the compiler find out what a name
t::x refers to, if t 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:
Let's wait until the user instantiates the template, and then later find out the real meaning of
t::x * f;. 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 by typename to tell the compiler to parse it in a certain way. The Standard says at (14.6/2):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.
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 with T f;, when T is a type template parameter. But for t::x f; to be a declaration, it must be written as typename 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:// t::x is taken as non-type, but as an expression the following misses an
// operator between the two names or a semicolon separating them.
t::x f;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:
boost::function f;It might look obvious to a human reader. Not so for the compiler. Imagine the following arbitrary definition of
boost::function and f:namespace boost { int function = 0; }
int main() {
int f = 0;
boost::function f;
}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 resulting bool against f. However as you might well know, boost::function in real life is a template, so the compiler knows (14.2/3):After name lookup (3.4) finds that a name is a template-name, if this name is followed by a
or .` in a class member access. You need to insert the keyword there too:this->template f(); // call a function templateDependencies
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 hav
Code Snippets
// t::x is taken as non-type, but as an expression the following misses an
// operator between the two names or a semicolon separating them.
t::x f;boost::function< int() > f;namespace boost { int function = 0; }
int main() {
int f = 0;
boost::function< int() > f;
}t::template f<int>(); // call a function templatethis->template f<int>(); // call a function templateContext
Stack Overflow Q#610245, score: 1480
Revisions (0)
No revisions yet.