I've been practicing polymorphism and using abstract classes lately by writing different implementations of simple data structures using abstract classes.
I've come across some strange compiler behavior and I'm not sure if I'm writing it wrong (and Visual Studio is offending the standard) or if it's a bug in G++.
The issue stems from the inheritance of typedefs inside template classes
ListInterface.h
1 2 3 4 5 6 7 8 9 10 11 12
#ifndef _LIST_INTERFACE_H_
#define _LIST_INTERFACE_H_
template <class T>
class ListInterface
{
public:
typedefunsignedint index_type;
//abstract member functions
};
#endif /* _LIST_INTERFACE_H_*/
ArrayList.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/* Include Guards and dependancy includes */
template <class T>
class ArrayList : public ListInterface<T>
{
public:
staticconst index_type DEFAULT_CAPACITY;
//rest of my class
};
template <class T>
consttypename ArrayList<T>::index_type ArrayList<T>::DEFAULT_CAPACITY = 10;
//rest of definition
While this compiles and runs just fine using Visual Studio 2008/2010, G++ gives a wall of errors (with only the first few dozen being related to the actual error) the rest just being compiler confusing I'm thinking.
In file included from main.cpp:3:
ArrayList.h:20: error: 'index_type' has not been declared
ArrayList.h:29: error: 'index_type' does not name a type
ArrayList.h:29: note: (perhaps 'typename ListInterface<T>::index_type' was inten
ded)
ArrayList.h:30: error: 'index_type' does not name a type
ArrayList.h:30: note: (perhaps 'typename ListInterface<T>::index_type' was inten
ded)
ArrayList.h:38: error: 'index_type' has not been declared
ArrayList.h:41: error: 'index_type' does not name a type
ArrayList.h:41: note: (perhaps 'typename ListInterface<T>::index_type' was inten
ded)
ArrayList.h:45: error: conflicting declaration 'const typename ArrayList<T>::ind
ex_type ArrayList<T>::DEFAULT_CAPACITY'
ArrayList.h:14: error: 'ArrayList<T>::DEFAULT_CAPACITY' has a previous declarati
on as 'const typename ListInterface<T>::index_type ArrayList<T>::DEFAULT_CAPACIT
Y'
ArrayList.h:45: error: declaration of 'const typename ListInterface<T>::index_ty
pe ArrayList<T>::DEFAULT_CAPACITY' outside of class is not definition
*add it just keeps on going, actually...*
From a quick google search it appears to have something to do with 'dependant names', but I have no idea on how to go about solving this compilation problem.
templates are weird with dependent / nondependent types. You really have to spell it out for the compiler.
index_type exists in ListInterface, not in ArrayList.
Here is what I did to get it compiling on GCC:
1 2 3 4 5 6 7 8 9
template <class T>
class ArrayList : public ListInterface<T>
{
public:
staticconsttypename ListInterface<T>::index_type DEFAULT_CAPACITY; // note ListInterface:: and typename
};
template <class T>
consttypename ListInterface<T>::index_type ArrayList<T>::DEFAULT_CAPACITY = 10; // ditto
Alternatively you could typedef it in ArrayList again:
1 2 3 4 5 6 7 8 9 10
template <class T>
class ArrayList : public ListInterface<T>
{
public:
typedeftypename ListInterface<T>::index_type index_type; // retypedef
staticconst index_type DEFAULT_CAPACITY; // now this works
};
template <class T>
consttypename ArrayList<T>::index_type ArrayList<T>::DEFAULT_CAPACITY = 10; // still need the hints here though
Retypedef'ing was the best solution in my case, otherwise I would have had to rename all my index_type variables to ListInterface<T>::index_type. Thanks a bunch.
Any idea why it compiles fine the way I had it with Visual Studio and had to explicitly typedef it again using g++? Is it simply Microsofts compiler is more advanced at resolving dependent names, or is it a standards vs language extensions deal between the two compilers, or is it just a flat out deficiency in g++?
Technically G++ is correct to the standard - typenames are not carried forward from base class to derived classes.
Microsoft is just allowing you to do the obvious (and is not in keeping with the standard)
[EDIT]
I should clarify that this is in regard to templates