Проблема с шаблонами в C++: "ожидаемое первичное выражение перед токеном`>'"

у меня есть следующий код в проект, я делаю для класса. У меня были проблемы с печатью заявления в течение нескольких часов, и я не мог найти то, что мне нужно в интернете.

вот мое определение шаблонного класса:

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;
    }
....
};

тогда проблема, с которой я сталкиваюсь, в печати:

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;
}

когда я пытаюсь скомпилировать с g++, я получаю следующее сообщение об ошибке:

oset.cc: 276: ошибка: ожидаемое первичное выражение перед ‘>’ токен

oset.cc: 276: error:’ i ' не был объявлен в этой области

проблема в закомментированную строку. Маркер">", дающий проблемы, находится непосредственно перед первым i. По какой-то причине ему не нравится <S>. Если я избавлюсь от <S> Он говорит мне, что ожидается ';' перед i

Я честно понятия не имею, что вызывает проблему. Я очень расстроен, и любая помощь будет высоко оценена. Спасибо!

1 ответов


for (oset<S>::iter<S> i = OS.begin(); i != OS.end(); ++i) { //error this line

вы должны использовать typename и template здесь:

for (typename oset<S>::template iter<S> i = OS.begin(); i != OS.end(); ++i) 

обратите внимание, что ни одно из следующих действий не будет работать:

oset<S>::iter<S> i              //error
typename oset<S>::iter<S> i     //error
oset<S>::template iter<S> i     //error

ваша ситуация такова, что вы должны использовать оба ключевых слова : typename а также template:

typename oset<S>::template iter<S> i  //ok

почему вам нужны оба ключевых слова здесь, объясняется @Johannes в этой теме:


несколько советов и улучшений

  • сделать итератор не шаблон. Использовать T везде, где вы используете U в своем определении.
  • переименовать класс iter to iterator. Сделайте его похожим на стандартный контейнер / итератор, чтобы вы могли использовать его в агорифмах, определенных в <algorithm>.

то есть, ваш класс должен выглядеть это:

class iterator {
    node<T> *pos;
    iterator(node<T>* n) : pos(n) { }
    friend class oset<T>; 
};

затем в for loop, вам понадобится только typename as:

typename oset<S>::iterator i //ok