【问题标题】:I inherit from std::iterator, but compiler does not recognise 'pointer' or 'reference'我从 std::iterator 继承,但编译器无法识别“指针”或“引用”
【发布时间】:2015-11-01 15:03:12
【问题描述】:

我正在制作自定义迭代器,但我很困惑 在模板化迭代器实现的情况下,是什么导致编译器无法识别 pointerreference 类型定义。

以下代码编译良好:

#include <iterator>

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

};

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

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

};

whole code here

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

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

根据note,似乎我不应该打扰使用std::iterator 结构,而是我应该手动复制typedef。 但这似乎太容易出错,以防 iterator 或 iterator_traits 将来获得额外的 typedef。

2。您认为我应该如何处理这些特征的定义(pointerreference 等)?

【问题讨论】:

标签: c++ templates iterator


【解决方案1】:

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

因为编译器不能排除您尝试提供std::iterator 的特化,其中pointerreference 不是类型定义,所以在模板定义时,从属名称永远不能解释为typedef

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

【讨论】:

  • 同意。我对所有超类都使用这种风格。如果将别名类型 base 设为私有,会稍微安全一些。
【解决方案2】:

现在您的基类是dependent type,它的成员pointerreference 也是。

你需要:

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

你可以轻松做到:

   typename It2::pointer operator-> () { return v; }
   typename It2::reference operator* () { return *v; }
// ^^^^^^^^^^^^^^

为什么?因为 C++ 很古怪,而且非常缺乏表达力。

【讨论】:

  • 投反对票? TRY IT YOURSELF
  • 或更准确地说,“为什么?因为编译器怎么会知道你意味着继承类型?你可能意味着当前命名空间中的某个类型,父命名空间或全局命名空间。”
  • @RichardHodges:没有其他语言的结构如此脆弱以至于需要这种混乱:P
  • 是否有另一种语言以编译时类型安全的方式支持相同范围的概念表达式?这是一个真正的问题。
  • @RichardHodges:必须在 C++ 中使用模板实现的内容可能会在非 C++ 中以另一种方式实现。您不能自动比较同类(这确实是重点)。您以编译时类型安全的方式向我询问了另一种具有相同概念表达式范围的语言,而不是使用 C++ 的模板概念这样做的语言。
【解决方案3】:

编译器对错误很清楚:

也许typename std::iterator&lt;std::random_access_iterator_tag, T&gt;::pointer 是故意的

因为pointer 已成为类型相关的名称。

【讨论】:

  • 在解释之前,任何人都不清楚为什么“也许......是有意的”。
  • 如果 clang 没有提供这个替代方案,我会被卡住。现在,我只是对声明operators 的最佳方式感到困惑
猜你喜欢
  • 2013-10-25
  • 1970-01-01
  • 2014-08-17
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多