假设我有一个容器类Box
,它提供了内部类const_iterator
和iterator
。因为我希望iterator
可以转换为const_iterator
,后者继承自前者:
class Box {
// ...
public:
class const_iterator : public std::iterator<std::random_access_iterator_tag, const int> { /* ... */ };
class iterator : public const_iterator { /* ... */ };
// ...
};
现在我想使用Google Test测试这些类。让我们声称begin()
和end()
不会返回相同的内容:
const Box a;
EXPECT_NE(a.begin(), a.end());
向编译错误问好:
no member named 'begin' in 'Box::const_iterator'
‘const class Box::const_iterator’ has no member named ‘begin’
有些研究让我在Google Test源代码中this template(请点击扩展文档的链接):
typedef int IsContainer;
template <class C>
IsContainer IsContainerTest(int /* dummy */,
typename C::iterator* /* it */ = NULL,
typename C::const_iterator* /* const_it */ = NULL) {
return 0;
}
这个模板魔术的结果是,如果EXPECT_*
的参数有iterator
和const_iterator
成员类,那么该类型被假定为容器类。知道了这一点,Google Test可以在预期失败时打印漂亮的人工可读报告,这很不错。
但是,有一个小细节:
// Note that we look for both C::iterator and C::const_iterator. The
// reason is that C++ injects the name of a class as a member of the
// class itself (e.g. you can refer to class iterator as either
// 'iterator' or 'iterator::iterator'). If we look for C::iterator
// only, for example, we would mistakenly think that a class named
// iterator is an STL container.
所以,如果我理解正确的话,那就意味着
Box::const_iterator
将自己作为名为const_iterator
的成员类,将std::iterator
作为名为iterator
的成员类。Box::iterator
将自己作为名为iterator
和Box::const_iterator
的成员类作为名为const_iterator
的成员类。因此,我的迭代器类看起来都像是Google Test的容器类!
如何设计我的迭代器类以使它们看起来不像容器?
我尝试的事情:
std::iterator
的超级类const_iterator
声明为private
。这通过隐藏const_iterator
成员类解决了iterator
的问题,但它仍然不允许我将a.begin()
作为参数传递给EXPECT_NE
,除非{{1}是a
。由于某种原因,Google Test似乎使用const
而不是iterator begin()
。const_iterator begin() const
超类。这是一个坏主意吗?我想我必须手动声明我的std::iterator
,还有什么我不会因为不延长std::iterator_traits
而失去?std::iterator
的超级类Box::const_iterator
声明为Box::iterator
。这可能是也可能不是一种选择,因为我必须重新声明我想要重用的方法(例如private
)。还有什么我忽略的吗?
operator++
答案 0 :(得分:1)
ThreeInts::iterator
不应继承ThreeInts::const_iterator
,而应单独实施。
class ThreeInts::iterator : public std::iterator< std::random_access_iterator_tag, int> { ... }
class ThreeInts::const_iterator : public std::iterator< std::random_access_iterator_tag, const int> { ... }
问题似乎是ThreeInts::const_iterator
两者都有名为const_iterator
和iterator
的成员(也就是构造函数)。同时使iterator
继承自const_iterator
不是常量,因为const_iterator
应该只保存指针/类似于const
数据。 STL容器还将两个迭代器分开。
在该代码中,代替定义迭代器类可能就足够了,只需定义
即可using iterator = int*;
using const_iterator = const int*;