我正在写一个自己的容器类,遇到了一个我无法理解的问题。这是显示问题的裸骨样本。
它由一个容器类和两个测试类组成:一个测试类使用std:vector编译得很好,第二个测试类试图以完全相同的方式使用我自己的容器类但是很难编译。 / p>#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告诉我:
test2.C:在成员函数'void TestClassMyContainer :: test()'中:
test2.C:51:错误:从'MyContainer :: iterator'转换为非标量类型'MyContainer :: const_iterator'请求
我不确定编译器想要将迭代器转换为我自己的类的const_iterator而不是STL矢量类的位置和原因。我究竟做错了什么?
答案 0 :(得分:10)
当您调用begin()
时,默认情况下编译器会创建对非const begin()
的调用。由于myc
不是const,因此无法知道使用const begin()
而不是非const begin()
。
STL迭代器包含一个强制转换运算符,允许iterator
以静默方式转换为const_iterator
。如果你希望这个工作,你需要添加一个像这样:
class iterator
{
public:
typedef iterator self_type;
inline iterator() { }
operator const_iterator() { return const_iterator(); }
};
或允许从const_iterator
构建iterator
,如此:
class const_iterator
{
public:
typedef const_iterator self_type;
const_iterator(iterator& ) {}
inline const_iterator() { }
};
答案 1 :(得分:3)
在容器iterator
中,类型必须可转换为const_iterator
。对于使用非可变(const)迭代器迭代可变容器的情况,需要它,因为这非常有意义。在你的情况下myc
是可变的(非const),但你在它上面创建一个const迭代器。
答案 2 :(得分:2)
您应该查看Boost.Iterators库,尤其是iterator_facade
和iterator_adaptor
部分。它们“从头开始”包含迭代器的构建。
它将向您展示如何在没有太多重复的情况下编写迭代器,因为除了const
限定本身之外,const和非const版本的代码大多数情况大致相同。使用模板可以编写一次,然后声明两种不同的类型,这就是库文档说明的内容。