-
Templated templates...
...my temple hurts.
I'm writing (potentially) template-heavy code, and I've encountered this problem which fortunately can be isolated:
Code:
#include <vector>
template <class a_type>
class a_class
{
public:
void foo()
{
std::vector <a_type>::iterator i;
}
};
Now when I try to compile this code in GCC it gives
Code:
In member function 'void a_class<a_type>::foo()': expected ';' before "i"
I'm thinking the reason is in the way the STL implements its iterators... you need a well-defined class for them. But I'm not sure.
EDIT: Okay, after fiddling around I found that using typename would resolve the error. (And finally got a chance to learn what the keyword did.) I'm still open to explanations...
-
Yup, I was just about to post and say "use the typename keyword" when I saw your EDIT.
The basic reason is that, when compiling code for a template, that the compiler has insufficient information to work out whether
Code:
std::vector<a_type>::iterator i;
is dealing with an expression (eg something that can be evaluated) or if it is a declaration (as you intend in this case). It may not be obvious, but a minor change makes even humans do a double take;
Code:
std::vector<a_type>::iterator *i;
because (unless we know the vector class off by heart) we don't know if this is declaring a pointer named i, of if it is silently multiplying some quantity named std::vector<a_type>::iterator to a variable named i and discarding the result.
In other words, the compiler has no means to know (until you actually instantiate your template with a particular type) what a_type is, so it does not look at the std::vector<> template, so it cannot deduce that std::vector<a_type>::iterator actually represents a type name rather than a part of an expression. An example of "part of an expression" is a data member within the std::vector<> template. Without the typename keyword, the compiler assumes that std::vector<a_type>::iterator is part of an expression, and therefore complains as yours has. The typename keyword tells the compiler that the next token (std::vector<a_type>::iterator) is a type name rather than part of an expression.
Some compilers get this wrong, and mistakenly let the code through, but then the most common problem is for some form of very obscure linker error.
-
Learn something everyday, eh... thanks grumpy. :)