我从std :: iterator继承,但编译器无法识别'指针'或'引用'

Gri*_*ngo 2 c++ templates iterator

我正在制作一个自定义迭代器,但我很困惑的是,在模板化迭代器实现的情况下,编译器无法识别pointer或者reference类型定义.

以下代码编译正常:

#include <iterator>

struct It : std::iterator<std::random_access_iterator_tag, int>
{
    int *v;
    pointer operator-> () { return v; }
    reference operator* () { return *v; }

};
Run Code Online (Sandbox Code Playgroud)

但是一旦我将我的自定义迭代器模板化,我就会收到错误:

#include <iterator>

template <class T>
struct It2 : std::iterator<std::random_access_iterator_tag, T>
{
    T *v;
    pointer operator-> () { return v; }
    reference operator* () { return *v; }

};
Run Code Online (Sandbox Code Playgroud)

整个代码在这里

error: 'pointer' does not name a type
note: (perhaps 'typename std::iterator<std::random_access_iterator_tag, T>::pointer' was intended)
error: 'reference' does not name a type
...
Run Code Online (Sandbox Code Playgroud)

1>为什么编译器看不到包含的pointerreference定义std::iterator

根据note,似乎我不应该使用std :: iterator结构,但我应该手动复制typedef.但是,如果迭代器或iterator_traits将来获得额外的typedef,那么这似乎太容易出错.

2.你认为我应该处理这些性状(的定义pointer,reference等等)?

小智 6

1>为什么编译器看不到std :: iterator中包含的指针和引用定义?

因为编译器不能排除您尝试提供std::iteratorwhere pointerreference不是类型定义的特化,所以从属名称永远不能被解释为typedefat模板定义时间.

2.您认为我应该如何处理这些特征的定义(指针,参考等)?

虽然typename每次都明确地限定它们,但你可以做的是将它们声明为一次,并在你的It2定义的其余部分依赖于那个声明:

#include <iterator>

template <class T>
struct It2 : std::iterator<std::random_access_iterator_tag, T>
{
    using base = std::iterator<std::random_access_iterator_tag, T>;
    using typename base::pointer;
    using typename base::reference;
    T *v;
    pointer operator-> () { return v; }
    reference operator* () { return *v; }
};
Run Code Online (Sandbox Code Playgroud)


Lig*_*ica 5

既然你的基类是一个依赖类型,那么它的成员pointerreference.

你需要:

  • 向编译器表明这些单词是类型
  • 向编译器指出这些单词是成员类型

你可以轻松地做到:

   typename It2::pointer operator-> () { return v; }
   typename It2::reference operator* () { return *v; }
// ^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

为什么?因为C++很古怪,因为它非常简单,而且非常难以理解.

  • @RichardHodges:没有其他语言如此虚弱,以至于需要这个混乱:P (2认同)