C++自己的容器类的iterator和const_iterator问题

发布于 2024-09-01 22:00:47 字数 1339 浏览 7 评论 0原文

我正在编写一个自己的容器类,但遇到了一个我无法理解的问题。这是显示问题的简单示例。

它由一个容器类和两个测试类组成:一个使用 std:vector 的测试类可以很好地编译,第二个测试类尝试以完全相同的方式使用我自己的容器类,但编译失败。

#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

template <typename T>
class MyContainer
{
public:
  
  class iterator
  {
  public:
    typedef iterator self_type;
    inline iterator() { }
  };

  class const_iterator
  {
  public:
    typedef const_iterator self_type;
    inline const_iterator() { }
  };
  
  iterator begin() {
    return iterator();
  }

  const_iterator begin() const {
    return const_iterator();
  }
};

// This one compiles ok, using std::vector
class TestClassVector
{
public:
  void test() {
    vector<int>::const_iterator I=myc.begin();
  }

private:
  vector<int> myc;
};

// this one fails to compile. Why?
class TestClassMyContainer
{
public:
  void test(){
    MyContainer<int>::const_iterator I=myc.begin();
  }

private:
  MyContainer<int> myc;
};


int main(int argc, char ** argv)
{
  return 0;
}

海湾合作委员会告诉我:

test2.C:在成员函数“void TestClassMyContainer::test()”中:

test2.C:51:错误:请求从“MyContainer::iterator”转换为非标量类型“MyContainer::const_iterator”

我不确定编译器想要将我自己的类的迭代器转换为 const_iterator 而不是 STL 向量类的迭代器的位置和原因。我做错了什么?

I'm writing an own container class and have run into a problem I can't get my head around. Here's the bare-bone sample that shows the problem.

It consists of a container class and two test classes: one test class using a std:vector which compiles nicely and the second test class which tries to use my own container class in exact the same way but fails miserably to compile.

#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

template <typename T>
class MyContainer
{
public:
  
  class iterator
  {
  public:
    typedef iterator self_type;
    inline iterator() { }
  };

  class const_iterator
  {
  public:
    typedef const_iterator self_type;
    inline const_iterator() { }
  };
  
  iterator begin() {
    return iterator();
  }

  const_iterator begin() const {
    return const_iterator();
  }
};

// This one compiles ok, using std::vector
class TestClassVector
{
public:
  void test() {
    vector<int>::const_iterator I=myc.begin();
  }

private:
  vector<int> myc;
};

// this one fails to compile. Why?
class TestClassMyContainer
{
public:
  void test(){
    MyContainer<int>::const_iterator I=myc.begin();
  }

private:
  MyContainer<int> myc;
};


int main(int argc, char ** argv)
{
  return 0;
}

gcc tells me:

test2.C: In member function ‘void TestClassMyContainer::test()’:

test2.C:51: error: conversion from ‘MyContainer::iterator’ to non-scalar type ‘MyContainer::const_iterator’ requested

I'm not sure where and why the compiler wants to convert an iterator to a const_iterator for my own class but not for the STL vector class. What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

楠木可依 2024-09-08 22:00:47

当您调用 begin() 时,编译器默认会创建对非常量 begin() 的调用。由于 myc 不是 const,它无法知道您打算使用 const begin() 而不是非 const begin().

STL 迭代器包含一个强制转换运算符,它允许将迭代器静默转换为 const_iterator。如果您希望它起作用,您还需要添加一个,如下所示:

class iterator
{
public:
    typedef iterator self_type;
    inline iterator() { }

    operator const_iterator() { return const_iterator(); }
};

或者允许从 iterator 构造 const_iterator,如下所示:

class const_iterator
{
public:
    typedef const_iterator self_type;

    const_iterator(iterator& ) {}
    inline const_iterator() { }
};

When you call begin() the compiler by default creates a call to the non-const begin(). Since myc isn't const, it has no way of knowing you mean to use the const begin() rather than the non-const begin().

The STL iterator contains a cast operator which allows an iterator to be silently converted to a const_iterator. If you want this to work you need to add one as well like so:

class iterator
{
public:
    typedef iterator self_type;
    inline iterator() { }

    operator const_iterator() { return const_iterator(); }
};

or allow const_iterator to be constructed from an iterator like so:

class const_iterator
{
public:
    typedef const_iterator self_type;

    const_iterator(iterator& ) {}
    inline const_iterator() { }
};
微凉徒眸意 2024-09-08 22:00:47

您应该查看 Boost.Iterators 库,尤其是 iterator_facadeiterator_adaptor 部分。它们包含“从头开始”构建迭代器。

它将向您展示如何在没有太多重复的情况下编写迭代器,因为大多数时候,除了 const 限定本身之外,const 和非 const 版本的代码大致相同。使用模板可以编写一次,然后声明两种不同的类型,这就是库文档所说明的内容。

You should have a look to the Boost.Iterators library, especially the iterator_facade and iterator_adaptor sections. They contain a build-up of an iterator "from scratch".

It will show you how to write iterators without too much duplication, because most of the times the code the const and non-const versions is about the same, apart from the const qualification itself. Using templates it's possible to write it once, then declare two different types, and that's what the library documentation illustrates.

毁虫ゝ 2024-09-08 22:00:47

在容器中,iterator 类型必须可转换为 const_iterator。当您使用不可变(常量)迭代器迭代可变容器的情况下,这是需要的,因为这非常有意义。在您的情况下, myc 是可变的(非常量),但您在其上创建了一个 const 迭代器。

In containers iterator type must be convertible to const_iterator. It is needed for the cases where you iterate through a mutable container using a non-mutable (const) iterator as this makes perfect sense. In your case myc is mutable (non-const), but you create a const iterator on that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文