c ++中的模板问题:"```token之前的预期主表达式"

Gar*_*att 6 c++ templates

我在上课的项目中有以下代码.我在打印声明上遇到了几个小时的麻烦,我无法在互联网上找到我需要的东西.

这是我的模板类定义:

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;
    }
....
};
Run Code Online (Sandbox Code Playgroud)

然后我遇到的问题是打印:

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;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试使用g ++编译时,我收到以下错误消息:

oset.cc:276:错误:在'>'标记之前预期的primary-expression

oset.cc:276:错误:'i'未在此范围内声明

问题出在注释行中.提出问题的'>'令牌直接在第一个之前i.出于某种原因,它不喜欢<S>.如果我摆脱<S>它它告诉我它期望';' 之前i

老实说,我不知道造成这个问题的原因.我非常沮丧,任何帮助都将受到高度赞赏.谢谢!

Naw*_*waz 9

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

你要用typenametemplate这里:

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

请注意,以下任何一项都不起作用:

oset<S>::iter<S> i              //error
typename oset<S>::iter<S> i     //error
oset<S>::template iter<S> i     //error
Run Code Online (Sandbox Code Playgroud)

您的情况是这样的,您必须使用这两个关键字:typename以及template:

typename oset<S>::template iter<S> i  //ok
Run Code Online (Sandbox Code Playgroud)

为什么你在这里需要两个关键字,@ Jehannes在本主题中解释了:


很少有建议和改进

  • 使迭代器类成为非模板.使用T无论你正在使用U中它的定义.
  • 同时将类重命名iteriterator.使它看起来像标准容器/迭代器,以便您可以在定义的算法中使用它<algorithm>.

也就是说,你的类应该是这样的:

class iterator {
    node<T> *pos;
    iterator(node<T>* n) : pos(n) { }
    friend class oset<T>; 
};
Run Code Online (Sandbox Code Playgroud)

然后在for循环中,你只需要typename:

typename oset<S>::iterator i //ok
Run Code Online (Sandbox Code Playgroud)