Wierd compiler error (don't worry, not much code)

Started by
5 comments, last by Brother Bob 17 years, 10 months ago
Hi all. I've stripped down my problem code but preserved my structure, which is why the code below looks meaningless, but can someone please tell me why the commented-out line generates the GCC error expected `;' before "iter" but the corresponding line in test.cpp does not? First, PT.hpp:
namespace T {
	template<unsigned int NUM, typename DATA>
	class PT {
		int x;
		// Stuff
		
		public:
			class iterator {
				int x;
				// stuff;
			};
	};
}
and D.hpp:
#include "PT.hpp"

namespace T {
	template<typename DAT>
	class D {
		private:
			static const unsigned int NUM = 3;
			
			class DT {
				int x;
				DAT d;
				// stuff
			};

			typedef PT<NUM, DT> X;
			X x;
		//	X::iterator iter;
		// The above line gives an error.
	};
}
and test.cpp:
#include "D.hpp"

typedef T::PT<3, int> Type;

int main(){
	Type t;
	Type::iterator i; // THIS LINE COMPILES FINE
}
The files as they are above will compile, as soon as I un-comment the line in D.hpp it errors. I don't understand how they're different. (Excuse the odd names.)
spraff.net: don't laugh, I'm still just starting...
Advertisement
Google "dependant names" or "two phase lookup". Basically until the compiler knows what X is it cannot know whether X::iterator is a static data member or a nested typedef. So it assumes it's a static data member unless you use the typename keyword. To fix it just prepend the keyword typename to the statement.

The equivalent in test.cpp is not a problem because the type of Type is known.

Σnigma
Looks like a compiler bug to me ... but to remove a very small difference can you try hard coding "3" in the template arg in the middle version to match the .cpp version? (instead of using the static const).

EDIT: Guess I was wrong.

[Edited by - Xai on May 31, 2006 8:56:52 PM]
You have to prefix it with typename as Enigma hinted. It works with the concrete instantiation of the template because then it can just look up the name and see that it's a type, not a member.
Okay, changing X::iterator iter; to typename X::iterator iter; works fine, thanks a lot, but I still don't understand the problem. Google is giving me far too in-depth results that can only be understood with a familiar copy of the language in-hand.

I thought I'd removed any ambiguity with typedef PT<NUM, DT> X; since there is no X defined anywhere else. I fail to see how adding "typename" gives the compiler any clue at all.
spraff.net: don't laugh, I'm still just starting...
Essentially, the compiler needs to know if X::iterator refers to a type or to a variable before it instantiates the template class. It assumes it refers to a variable unless you use the typename keyword.
The problem is that X is a type than depends on template parameters, so the meaning of X::iterator could be different depending on what the template parameters are. Is X::iterator another type, or is it a static data member? If the compiler doesn't know, it assume it is a static data member. The problem is not with X itself, but with iterator in X.

To tell the compiler that X::iterator is a type, you add the typename keyword.

This topic is closed to new replies.

Advertisement