【问题标题】:Dereferencing operator for custom array iterator自定义数组迭代器的取消引用运算符
【发布时间】:2021-06-10 04:43:23
【问题描述】:

我正在练习为自定义类实现随机访问迭代器:

 template<typename T>
    class Array{
    friend class Iterator;
    private:
        std::unique_ptr<T[]> data;
        int front_index;
        //other variables
    public:
        class Iterator{
            friend class Array<T>;
        private:
            int position;
        public:
            Iterator(int pos) {position = pos; }
            //some other iterator functions
            template<typename T>
            T operator*(){
                return data[position];
            }
        };
        Iterator begin() const { return Iterator(front_index); }
        //other Array functions(insert, delete)
    };

但是当我调用这段代码时:

Array<int> a;
//insert some elements
Array<int>::Iterator iter1 = a.begin();
cout << "iterator is " << *iter1 << endl; 

它给出了以下错误:

C++ no operator matches these operands, operand types are: * Array<int>::Iterator 

似乎错误来自return data[position]; 行。如果我只写 return position 代码运行,但这不是我想要的(我希望当我取消引用时 ierator 返回特定位置的元素。感谢任何输入!

【问题讨论】:

  • 看起来像是一条错误的错误消息。 dataIterator 中无法访问,因为您从未告诉它data 是什么。 C++ 中的内部classes 与外部class 没有自动关系。
  • @eerorika dataArray 的成员。而Iterator 成为朋友并不会神奇地使其能够访问Arrays 成员。
  • @super 哦,是的,这是真的。 name 可访问,但无法通过非限定查找找到。

标签: c++ iterator overloading


【解决方案1】:

它给出了以下错误:

C++ no operator matches these operands, operand types are: * Array<int>::Iterator

似乎错误来自返回数据[位置];线。如果我只写代码运行的返回位置,但这不是我想要的(我希望当我取消引用时 ierator 返回特定位置的元素。

不应该,因为这对解决 这个 错误没有任何帮助。不清楚你为什么会这样想。


您的示例存在三个基本问题。一种是您有嵌套模板,其中内部模板参数隐藏了外部模板参数。这在 C++ 中是不允许的,导致如下错误:

error: declaration of template parameter 'T' shadows template parameter

简单的解决方案是为任何嵌套模板使用另一个名称。

另一个问题是您引用的问题。阅读错误消息进一步引导我们找到解决方案:

 error: no match for 'operator*' (operand type is 'Array<int>::Iterator')
   35 |     cout << "iterator is " << *iter1 << endl;
      |                               ^~~~~~
<source>:19:15: note: candidate: 'template<class T> T Array<T>::Iterator::operator*() [with T = T; T = int]'
   19 |             T operator*(){
      |               ^~~~~~~~
<source>:19:15: note:   template argument deduction/substitution failed:
<source>:35:32: note:   couldn't deduce template parameter 'T'
   35 |     cout << "iterator is " << *iter1 << endl;

编译器不知道要使用哪个模板参数,因为它不能从参数中推导出来,而且您没有指定任何参数。从技术上讲,这可以通过明确指定参数来解决:

<< iter1.operator*<int>()

但是,我质疑 为什么 间接运算符首先是模板?为什么不总是返回外部模板的T?我建议将其设为常规功能:

// not a template
T   // this is the outer template parameter
operator*(){

这些修复后可以看到第三个问题:

error: invalid use of non-static data member 'Array<int>::data'
   19 |                 return data[position];

这是您建议的更改“解决”的错误 - 从某种意义上说,程序变得结构良好。它只是没有做任何有意义的事情。

问题当然是迭代器没有成员data。一个典型的解决方案是存储一个指向数组元素的非拥有指针,而不仅仅是一个本身不能用于查找数组元素的位置:

T* data;

T operator*(){
    return *data;

事实上,由于指针是数组的迭代器,如果你懒惰,你可以简单地做而不是定义一个自定义类:

using Iterator = int*;

也就是说,自定义类可以让您在编译时捕获一些错误,所以这是一个很好的设计。

【讨论】:

  • 我仍然不明白:Iterator 实例如何能够访问Array 实例的data 成员(不涉及该Array 实例)?除了嵌套类 - 实例不是嵌套的......
  • @Scheff 哦,是的。这是 OP 建议的更改是“解决方案”的代码的另一个问题。
  • typename Iterator begin() const { return Iterator(const_cast&lt;Array&lt;T&gt;*&gt;(this), front_index); }我通过这种方式获取数据成员,不知道这样是否有效
猜你喜欢
  • 2013-12-17
  • 2017-02-22
  • 2016-01-25
  • 1970-01-01
  • 2020-07-14
  • 1970-01-01
  • 1970-01-01
  • 2012-11-08
  • 2018-09-18
相关资源
最近更新 更多