I tried googling this, but I was unable to come up with a suitable answer. Could any C++ gurus tell me why C++ requires you to declare OuterClass<T>::Innerclass with the typename keyword?
I am a TA for a data structures course and I see this error all of the time. I know to tell my students that they need to put typename in front of the return type, but I am unable to explain why this is required.
Thanks.
That's because of the two-phase name lookup in templates. When the compiler sees Innerclass it must know whether that name is a type or not (is could, for example, be a static member of type int for some specialization of OuterClass). So it supposes it is NOT a type name unless you say so. typename must be used in templates and only on names dependent on the template parameter. HTH
example:
template <class T>
class X
{
typedef T XXX;
};
template<>
class X<char>
{
static int XXX;
};
template<class T>
class Y
{
// X<T>::XXX member; invalid XXX is not assumed to be a type!
typename X<T>::XXX member;
//we explicitly specify that XXX is a type; Later, upon instantiation, we will verify that
};
OuterClass<T>::Innerclass
That because Innerclass represents a type (as I can see from your question) so you need to add the keyword typename before OuterClass<T>::Innerclass
Example :
template <class T>
void foo() {
T::iterator * iter;
...
}
Without typename T::iterator * iter; would be interpreted as multiplication operation between T::iterator and iter
Related
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Officially, what is typename for?
Where and why do I have to put the template and typename keywords?
consider the code below:
template<class K>
class C {
struct P {};
vector<P> vec;
void f();
};
template<class K> void C<K>::f() {
typename vector<P>::iterator p = vec.begin();
}
Why is the "typename" keyword necessary in this example?
Are there any other cases where "typename" must be specified?
Short answer: Whenever referring to a nested name that is a dependent name, i.e. nested inside a template instance with unknown parameter.
Long answer: There are three tiers of entities in C++: values, types, and templates. All of those can have names, and the name alone doesn't tell you which tier of entity it is. Rather, the information about the nature of a name's entity must be inferred from the context.
Whenever this inference is impossible, you have to specify it:
template <typename> struct Magic; // defined somewhere else
template <typename T> struct A
{
static const int value = Magic<T>::gnarl; // assumed "value"
typedef typename Magic<T>::brugh my_type; // decreed "type"
// ^^^^^^^^
void foo() {
Magic<T>::template kwpq<T>(1, 'a', .5); // decreed "template"
// ^^^^^^^^
}
};
Here the names Magic<T>::gnarl, Magic<T>::brugh and Magic<T>::kwpq had to be expliciated, because it is impossible to tell: Since Magic is a template, the very nature of the type Magic<T> depends on T -- there may be specializations which are entirely different from the primary template, for example.
What makes Magic<T>::gnarl a dependent name is the fact that we're inside a template definition, where T is unknown. Had we used Magic<int>, this would be different, since the compiler knows (you promise!) the full definition of Magic<int>.
(If you want to test this yourself, here's a sample definition of Magic that you can use. Pardon the use of constexpr in the specializaation for brevity; if you have an old compiler, feel free to change the static member constant declaration to the old-style pre-C++11 form.)
template <typename T> struct Magic
{
static const T gnarl;
typedef T & brugh;
template <typename S> static void kwpq(int, char, double) { T x; }
};
template <> struct Magic<signed char>
{
// note that `gnarl` is absent
static constexpr long double brugh = 0.25; // `brugh` is now a value
template <typename S> static int kwpq(int a, int b) { return a + b; }
};
Usage:
int main()
{
A<int> a;
a.foo();
return Magic<signed char>::kwpq<float>(2, 3); // no disambiguation here!
}
The typename keyword, is needed because iterator is a dependent type on P. The compiler can't guess if iterator refers to a value or a type, so it assume its a value unless you yell typename. It's needed whenever there is a type dependent on a template argument, in a context that either types or values would be valid. For instance, as base classes typename is not needed since a base class must be a type.
On the same subject, there is a template keyword used to let the compiler know that some dependent name is a template function instead of a value.
The typename keyword is needed whenever a type name depends on a template parameter, (so the compiler can 'know' the semantics of an identifier (type or value) without having a full symbol table at the first pass).
Not in the same meaning, and a bit less common, the lone typename keyword can also be useful when using generic template parameters: http://ideone.com/amImX
#include <string>
#include <list>
#include <vector>
template <template <typename, typename> class Container,
template <typename> class Alloc = std::allocator>
struct ContainerTests
{
typedef Container<int, Alloc<int> > IntContainer;
typedef Container<std::string, Alloc<int> > StringContainer;
//
void DoTests()
{
IntContainer ints;
StringContainer strings;
// ... etc
}
};
int main()
{
ContainerTests<std::vector> t1;
ContainerTests<std::list> t2;
t1.DoTests();
t2.DoTests();
}
So I have this code:
#include "type_traits"
struct A{
int member;
};
struct B{
typedef A object;
typedef int member;
};
typedef std::integral_constant<B::member, B::object::*, &A::member> type;
But if I change the final line to:
typedef std::integral_constant<typename B::member, typename B::object::*, &A::member> type;
The program will not compile....
Why does adding the typename specifier cause the program to not compile? This is especially surprising to me because I thought I needed it in this case.
Note:
Using gcc 5.1.0
You cannot add typename everywhere you want to specify a type. You can only, and require to add typename when you use a dependent type name.
A dependent name is something like this:
template<typename T>
void foo() { (void)T::member(); }
Is T::member a type, or a member function named member? The compiler will assume it's not a type by default. If it is a type, you must specify typename to disambiguate.
template<typename T>
void foo() { (void)typename T::member(); }
Now the compiler is told to assume that T::member is indeed a type.
However, the C++ syntax only allow it in cases that the nature of T::member cannot be known. So when dealing with know types, like your code, the compiler already know that these members are types. There's nothing to desambiguate.
If you were to change you typedef by a template alias, it would require typename as you wrote:
template<typename C, typename D> // v----- Type of pointer to member?
using type = std::integral_constant<typename D::member D::object::*, &C::member>;
// Here, D::object::* don't need typename, ----^
// since only types are allowed here
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Officially, what is typename for?
Where and why do I have to put the template and typename keywords?
consider the code below:
template<class K>
class C {
struct P {};
vector<P> vec;
void f();
};
template<class K> void C<K>::f() {
typename vector<P>::iterator p = vec.begin();
}
Why is the "typename" keyword necessary in this example?
Are there any other cases where "typename" must be specified?
Short answer: Whenever referring to a nested name that is a dependent name, i.e. nested inside a template instance with unknown parameter.
Long answer: There are three tiers of entities in C++: values, types, and templates. All of those can have names, and the name alone doesn't tell you which tier of entity it is. Rather, the information about the nature of a name's entity must be inferred from the context.
Whenever this inference is impossible, you have to specify it:
template <typename> struct Magic; // defined somewhere else
template <typename T> struct A
{
static const int value = Magic<T>::gnarl; // assumed "value"
typedef typename Magic<T>::brugh my_type; // decreed "type"
// ^^^^^^^^
void foo() {
Magic<T>::template kwpq<T>(1, 'a', .5); // decreed "template"
// ^^^^^^^^
}
};
Here the names Magic<T>::gnarl, Magic<T>::brugh and Magic<T>::kwpq had to be expliciated, because it is impossible to tell: Since Magic is a template, the very nature of the type Magic<T> depends on T -- there may be specializations which are entirely different from the primary template, for example.
What makes Magic<T>::gnarl a dependent name is the fact that we're inside a template definition, where T is unknown. Had we used Magic<int>, this would be different, since the compiler knows (you promise!) the full definition of Magic<int>.
(If you want to test this yourself, here's a sample definition of Magic that you can use. Pardon the use of constexpr in the specializaation for brevity; if you have an old compiler, feel free to change the static member constant declaration to the old-style pre-C++11 form.)
template <typename T> struct Magic
{
static const T gnarl;
typedef T & brugh;
template <typename S> static void kwpq(int, char, double) { T x; }
};
template <> struct Magic<signed char>
{
// note that `gnarl` is absent
static constexpr long double brugh = 0.25; // `brugh` is now a value
template <typename S> static int kwpq(int a, int b) { return a + b; }
};
Usage:
int main()
{
A<int> a;
a.foo();
return Magic<signed char>::kwpq<float>(2, 3); // no disambiguation here!
}
The typename keyword, is needed because iterator is a dependent type on P. The compiler can't guess if iterator refers to a value or a type, so it assume its a value unless you yell typename. It's needed whenever there is a type dependent on a template argument, in a context that either types or values would be valid. For instance, as base classes typename is not needed since a base class must be a type.
On the same subject, there is a template keyword used to let the compiler know that some dependent name is a template function instead of a value.
The typename keyword is needed whenever a type name depends on a template parameter, (so the compiler can 'know' the semantics of an identifier (type or value) without having a full symbol table at the first pass).
Not in the same meaning, and a bit less common, the lone typename keyword can also be useful when using generic template parameters: http://ideone.com/amImX
#include <string>
#include <list>
#include <vector>
template <template <typename, typename> class Container,
template <typename> class Alloc = std::allocator>
struct ContainerTests
{
typedef Container<int, Alloc<int> > IntContainer;
typedef Container<std::string, Alloc<int> > StringContainer;
//
void DoTests()
{
IntContainer ints;
StringContainer strings;
// ... etc
}
};
int main()
{
ContainerTests<std::vector> t1;
ContainerTests<std::list> t2;
t1.DoTests();
t2.DoTests();
}
How can I make the following code work? During compilation I get an error telling me that the searchForResource function has no return type.
template<class T>
class ResourceManager
{
private:
struct ResourceWrapper;
std::list<ResourceWrapper*> resources_; // This compiles fine
std::list<ResourceWrapper*>::iterator // Error occurs here
searchForResource(const std::string& file);
};
Also, is this how I would define the searchForResource function?
template<class t>
std::list<typename ResourceManager<T>::ResourceWrapper*>::iterator
ResourceManager<T>::searchForResource(const std::string& file)
{
// ...
}
std::list<ResourceWrapper*>::iterator is hard for the compiler to understand. Prefix it with typename in both the implementation and the declaration to let the compiler know that it's a type.
Like so:
typename std::list<ResourceWrapper*>::iterator searchForResource(const std::string& file);
template<class T>
class ResourceManager
{
private:
struct ResourceWrapper;
std::list<ResourceWrapper*> resources_;
// | typename lost here
// V
typename std::list<ResourceWrapper*>::iterator
searchForResource(const std::string& file);
};
template<class T>
// | typename lost here asterisk lost here |
// V V
typename std::list<typename ResourceManager<T>::ResourceWrapper*>::iterator
ResourceManager<T>::searchForResource(const std::string& file)
{
return ...
}
There is a rule of thumb to avoid such compilation errors.
Whenever you are declaring a variable or function, with a template followed by scope resolution operator :: then always put a keyword typename in front of the definition.
For example,
MyNameSpace::MyClass<T> x; // Ok; because template is NOT followed by scope resolution
MyNameSpace::MyClass<T>::MyType x; // Error; MyType can be a variable or a type; so put typename ahead
Same thing is applicable to function declaration also.
I think you're missing a typename keyword.
The problem is that ResourceWrapper is a dependent name *(it's definition depends on the type argument T), and that makes std::list< ResourceWrapper * > a dependent type name. Templates are checked in two passes, during the first pass, correctness of the template without actual type substitution is checked. Now when you type std::list< ResourceWrapper* >::iterator the compiler cannot know upfront that iterator is in fact a type and not an static attribute or member of the class std::list< ResourceWrapper* > because of the type being dependent and the T not yet being substituted.
You have to hint the compiler as to inform it that the iterator is indeed a type by using the typename keyword, as others have already mentioned before:
typename std::list< ResourceWrapper* >::iterator
Without seeing the rest of the code, I cannot say, but it seems as if ResourceWrapper should actually not be a dependent type on T. If it is in fact non-dependent, you should move the type outside of the class template. in that case, the typename will no longer be required:
struct ResourceWrapper;
template <typename T>
class ResourceManager {
std::list<ResourceWrapper*>::iterator searchForResource(const std::string& file);
...
Because it is defined outside of the template there is a single definition for all possible instantiations of the ResourceManager template, now ResourceWrapper is no longer dependent on T, and typename is no longer needed (nor correct).
* Why is ResourceWrapper dependent and how could this affect the code.
The reason that ResourceWrapper is dependent on the type T is easier seen by discussing the fully qualified name: ::ResourceManager<T>::ResourceWrapper. The T is part of the type, and as such T affects the actual definition of ResourceWrapper. This is somehow a contrived example in that you can arguably say that if the compiler is parsing this particular template, then it must know that ResourceWrapper is a type, and thus that std::list< ResourceWrapper*>::iterator is a type... and here is the problem. There is no particular reason not to have an specialization of the std::list template for a particular instantiation of ResourceManager:
namespace std { // you should in general not add things to the std namespace!
// but the implementation can
template <>
struct list< ResourceManager<int>::ResourceWrapper > {
static const int iterator = 5;
...
};
}
Again, contrived, but the compiler cannot possibly know upfront while parsing the template that such an specialization will not be present before you actually instantiate the template with a particular type.
you have forward declaration of ResourceWrapper struct which is good enough for the line that compiles fine, but you are getting the error because at that point compiler needs full type declaration for ResourceWrapper struct. (possibly your answer, this code actually compiles fine with VS2008)
On occasion I've seen some really indecipherable error messages spit out by gcc when using templates... Specifically, I've had problems where seemingly correct declarations were causing very strange compile errors that magically went away by prefixing the typename keyword to the beginning of the declaration... (For example, just last week, I was declaring two iterators as members of another templated class and I had to do this)...
What's the story on typename?
Following is the quote from Josuttis book:
The keyword typename was introduced to
specify that the identifier that
follows is a type. Consider the
following example:
template <class T>
Class MyClass
{
typename T::SubType * ptr;
...
};
Here, typename is used to clarify that
SubType is a type of class T. Thus,
ptr is a pointer to the type
T::SubType. Without typename, SubType
would be considered a static member.
Thus
T::SubType * ptr
would be a multiplication of value
SubType of type T with ptr.
Stan Lippman's BLog post suggests :-
Stroustrup reused the existing class
keyword to specify a type parameter
rather than introduce a new keyword
that might of course break existing
programs. It wasn't that a new keyword
wasn't considered -- just that it
wasn't considered necessary given its
potential disruption. And up until the
ISO-C++ standard, this was the only
way to declare a type parameter.
So basically Stroustrup reused class keyword without introducing a new keyword which is changed afterwards in the standard for the following reasons
As the example given
template <class T>
class Demonstration {
public:
void method() {
T::A *aObj; // oops …
// …
};
language grammar misinterprets T::A *aObj; as an arithmetic expression so a new keyword is introduced called typename
typename T::A* a6;
it instructs the compiler to treat the subsequent statement as a declaration.
Since the keyword was on the payroll,
heck, why not fix the confusion caused
by the original decision to reuse the
class keyword.
Thats why we have both
You can have a look at this post, it will definitely help you, I just extracted from it as much as I could
Consider the code
template<class T> somefunction( T * arg )
{
T::sometype x; // broken
.
.
Unfortunately, the compiler is not required to be psychic, and doesn't know whether T::sometype will end up referring to a type name or a static member of T. So, one uses typename to tell it:
template<class T> somefunction( T * arg )
{
typename T::sometype x; // works!
.
.
In some situations where you refer to a member of so called dependent type (meaning "dependent on template parameter"), the compiler cannot always unambiguously deduce the semantic meaning of the resultant construct, because it doesn't know what kind of name that is (i.e. whether it is a name of a type, a name of a data member or name of something else). In cases like that you have to disambiguate the situation by explicitly telling the compiler that the name belongs to a typename defined as a member of that dependent type.
For example
template <class T> struct S {
typename T::type i;
};
In this example the keyword typename in necessary for the code to compile.
The same thing happens when you want to refer to a template member of dependent type, i.e. to a name that designates a template. You also have to help the compiler by using the keyword template, although it is placed differently
template <class T> struct S {
T::template ptr<int> p;
};
In some cases it might be necessary to use both
template <class T> struct S {
typename T::template ptr<int>::type i;
};
(if I got the syntax correctly).
Of course, another role of the keyword typename is to be used in template parameter declarations.
The secret lies in the fact that a template can be specialized for some types. This means it also can define the interface completely different for several types. For example you can write:
template<typename T>
struct test {
typedef T* ptr;
};
template<> // complete specialization
struct test<int> { // for the case T is int
T* ptr;
};
One might ask why is this useful and indeed: That really looks useless. But take in mind that for example std::vector<bool> the reference type looks completely different than for other Ts. Admittedly it doesn't change the kind of reference from a type to something different but nevertheless it could happen.
Now what happens if you write your own templates using this test template. Something like this
template<typename T>
void print(T& x) {
test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
it seems to be ok for you because you expect that test<T>::ptr is a type. But the compiler doesn't know and in deed he is even advised by the standard to expect the opposite, test<T>::ptr isn't a type. To tell the compiler what you expect you have to add a typename before. The correct template looks like this
template<typename T>
void print(T& x) {
typename test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
Bottom line: You have to add typename before whenever you use a nested type of a template in your templates. (Of course only if a template parameter of your template is used for that inner template.)
Two uses:
As a template argument keyword (instead of class)
A typename keyword tells the compiler that an identifier is a type (rather than a static member variable)
template <typename T> class X // [1]
{
typename T::Y _member; // [2]
}
I think all of the answers have mentioned that the typename keyword, is used in two different cases:
a) When declaring a template type parameter. e.g.
template<class T> class MyClass{}; // these two cases are
template<typename T> class MyNewClass{}; // exactly the same.
Which there is no difference between them and they are EXACTLY the same.
b) Before using a nested dependent type name for a template.
template<class T>
void foo(const T & param)
{
typename T::NestedType * value; // we should use typename here
}
Which not using typename leads to parsing/compilation errors.
What I want to add to the second case, as mentioned in Scot Meyers book Effective C++, is that there is an exception of using typename before a nested dependant type name. The exception is that if you use the nested dependant type name either as a base class or in a member initialization list, you should not use typename there:
template<class T>
class D : public B<T>::NestedType // No need for typename here
{
public:
D(std::string str) : B<T>::NestedType(str) // No need for typename here
{
typename B<T>::AnotherNestedType * x; // typename is needed here
}
}
Note: Using typename for the second case (i.e. before nested dependent type name) is not needed since C++20.
#include <iostream>
class A {
public:
typedef int my_t;
};
template <class T>
class B {
public:
// T::my_t *ptr; // It will produce compilation error
typename T::my_t *ptr; // It will output 5
};
int main() {
B<A> b;
int my_int = 5;
b.ptr = &my_int;
std::cout << *b.ptr;
std::cin.ignore();
return 0;
}