为什么我不能将 std::iterator<>::reference 与模板一起使用?

问题描述

我尝试这样做

template <class V>
class myiterator: std::iterator<std::random_access_iterator_tag,V>{
    reference a;
};

就像这个例子

class myiterator: std::iterator<std::random_access_iterator_tag,int>{
    reference a;
};

但是我得到了一个错误“‘reference’没有命名类型”。如何将 std::iterator::reference 与模板一起使用?

解决方法

不会找到名称 reference,因为不会在依赖基类 std::iterator<std::random_access_iterator_tag,V> 中查找非依赖名称,该基类取决于模板参数 V

您可以将 reference 设为依赖名称:

template <class V>
class myiterator: std::iterator<std::random_access_iterator_tag,V>{
    typename std::iterator<std::random_access_iterator_tag,V>::reference a;
};

另一方面,非模板版本没有这样的问题。

,

名称reference是在基类中声明的,基类是一个依赖类型(它的类型依赖于V)。有适用于这种情况的特殊规则:当编译器看到名称 reference 时,它不会搜索依赖的基类范围,因此不会找到名称。为了强制编译器搜索依赖的基类作用域,您必须限定名称。

您可能认为 iterator::reference 可以解决问题。不幸的是,这也不起作用。 iterator 作为 std::iterator<std::random_access_tag,V> 的简写本身在基类中声明为它的“注入类名”。所以 iterator 也不会被找到,除非它被某些东西限定。

您可以长时间输入:typename std::iterator<std::random_access_tag,V>::reference a;。一种更易读的方式是:

using base = typename myiterator::iterator;
typename base::reference a;

您可以在 base:: 类定义的其余部分期间使用 myiterator 强制在基类范围内查找。

在 C++20 中,可以从这些上下文中省略 typename