Problem with templates in C ++: "Expected primary expression before`> `token"
I have the following code in a project that I am doing for a class. I had problems with the expression for printing for several hours, and I could not find what I needed on the Internet.
Here is my definition of a template class:
template <class T> class oset { template <class U> class node { ..... }; ..... public: template <class U> class iter { node<U> *pos; // node _before_ the one with this->operator* // constructor is private: iter(node<U>* n) : pos(n) { } friend class oset<U>; .... }; private: iter<T> start; // initialized in the constructors below iter<T> finish; // initialized in the constructors below public: iter<T> begin() { return start; } iter<T> end() { return finish; } .... }; Then the problem I have is in print:
template <class S> void print(oset<S>& OS) { for (oset<S>::iter<S> i = OS.begin(); i != OS.end(); ++i) { // ^-- error is on previous line cout << *i << " "; } cout << endl; } When I try to compile with g ++, I get the following error message:
oset.cc:276: error: expected primary expression before '> token
oset.cc:276: error: 'i was not declared in this area
The problem is in the comments. Problems with the '>' marker are immediately before the first i . For some reason, <S> doesn't like it. If I get rid of <S> , he will tell me what he expects ';' before i
I honestly have no idea what causes the problem. I am very upset and any help would be greatly appreciated. Thanks!
for (oset<S>::iter<S> i = OS.begin(); i != OS.end(); ++i) { //error this line Here you should use typename and template :
for (typename oset<S>::template iter<S> i = OS.begin(); i != OS.end(); ++i) Please note that none of the following will work:
oset<S>::iter<S> i //error typename oset<S>::iter<S> i //error oset<S>::template iter<S> i //error Your situation is that you should use both keywords: typename , as well as template :
typename oset<S>::template iter<S> i //ok Why you need both keywords here is explained by @Johannes in this section:
Some tips and improvements
- Make the iterator class not a template. Use
Twherever you useUin your definition. - Also rename the class from
itertoiterator. Make it look like a standard container / iterator so that you can use it in the agorites defined in<algorithm>.
That is, your class should look like this:
class iterator { node<T> *pos; iterator(node<T>* n) : pos(n) { } friend class oset<T>; }; Then in a for loop you will need a typename like:
typename oset<S>::iterator i //ok