如何使迭代器类看起来不像容器类?

埃米尔·隆伯格

前提

假设我有一个Box提供内部类const_iterator的容器类iterator因为我希望将aiterator转换为a 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测试这些类。断言thebegin()end()不要返回相同的东西:

const Box a;
EXPECT_NE(a.begin(), a.end());

向编译错误问好:

  • 铛: no member named 'begin' in 'Box::const_iterator'
  • g ++: ‘const class Box::const_iterator’ has no member named ‘begin’

原因

一些研究使我在Google Test源代码中找到了该模板(请参阅扩展文档的链接):

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_*具有iteratorconst_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_iteratorstd::iterator一个名为的成员类iterator
  • Box::iterator有一个名为的成员类iteratorBox::const_iterator名为的成员类const_iterator

因此,我的两个迭代器类都看起来像Google Test的容器类!

问题

如何设计迭代器类,使它们看起来不像容器?

我尝试过的事情:

  • 声明asstd::iterator超类通过隐藏成员类解决了问题,但是除非我是is 否则它仍然不允许我作为参数传递似乎是Google Test而非出于某种原因使用const_iteratorprivateconst_iteratoriteratora.begin()EXPECT_NEaconstiterator begin()const_iterator begin() const
  • std::iterator完全删除超类。这是一个坏主意吗?我想我必须std::iterator_traits手动声明我的代码,否则如果不进行扩展,还会丢失其他内容std::iterator吗?
  • 声明asBox::const_iterator超类这可能是选项,也可能不是选项,因为我不得不重新声明我想重用的方法(例如)。Box::iteratorprivateoperator++

还有什么我忽略的吗?


这个例子

#include<iterator>
#include <memory> //unique_ptr<T>
#include <gtest/gtest.h>

class ThreeInts {
  std::unique_ptr<int[]> v;

  public:
  ThreeInts() : v(new int[3]) { v[0] = 0; v[1] = 1; v[2] = 2; };
  ThreeInts(int val) : ThreeInts() { v[0] = val; v[1] = val; v[2] = val; };

  bool operator==(const ThreeInts& other) const {
    return v[0] == other.v[0] && v[1] == other.v[1] && v[2] == other.v[2];
  }

  class const_iterator : public std::iterator<std::random_access_iterator_tag, const int> {
  protected:
    int* p;
  public:
    explicit const_iterator(int* p) : p(p) {}
    const_iterator& operator++() { ++p; return *this; }
    bool operator==(const const_iterator& rhs) const { return p == rhs.p; }
    bool operator!=(const const_iterator& rhs) const { return p != rhs.p; }
    int operator*() const { return *p; }
  };

  class iterator : public const_iterator {
  public:
    explicit iterator(int* p) : const_iterator(p) {}
    int& operator*() const { return *p; }
  };

  iterator begin() { return iterator(v.get()); }
  iterator end() { return iterator(v.get()+3); }
  const_iterator begin() const { return const_iterator(v.get()); }
  const_iterator end() const { return const_iterator(v.get()+3); }
};

TEST(ThreeInts, ThisTestCompilesAndPrettyFailureMessagesAreShown) {
  const ThreeInts a(1), b(2);
  ThreeInts c(1), d(2);
  EXPECT_EQ(a, b);
  EXPECT_EQ(a, c);
  EXPECT_EQ(c, d);
}

TEST(ThreeInts, ThisTestCompilesIfTheStdIteratorParentIsPrivate) {
  const ThreeInts a;
  EXPECT_NE(a.begin(), a.end());
}

TEST(ThreeInts, ThisTestAlsoCompilesIfTheStdIteratorParentIsPrivateButItIsAHassle) {
  ThreeInts a;
  ThreeInts::const_iterator beg = a.begin();
  ThreeInts::const_iterator end = a.end();
  //EXPECT_NE(beg, end); // Compile error unless the std::iterator superclass is private
}

TEST(ThreeInts, ThisTestDoesNotCompileEvenIfTheStdIteratorParentIsPrivate) {
  ThreeInts a;
  //EXPECT_NE(a.begin(), a.end());
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
特伦

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(也称为构造函数)。另外,进行iteratorfrom继承const_iterator不是const正确的,因为const_iterator应当仅持有一个指针/类似于const数据。STL容器还将两个迭代器分开。

在该代码中,只需定义简单的定义即可,而不是定义迭代器类

using iterator = int*;
using const_iterator = const int*;

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何制作看起来不像按钮的Glyphicon按钮

来自分类Dev

Django:看起来不像模块路径

来自分类Dev

CSV文件看起来不像表格

来自分类Dev

我的iPhone模拟器看起来不像其他人的

来自分类Dev

无业游民的触发器并不像看起来那样简单

来自分类Dev

Cloud Ubuntu 服务器(Ubuntu 16.04) tar:这看起来不像 tar 存档

来自分类Dev

如何制作一个其构造函数看起来像内置类的构造函数的类?

来自分类Dev

焦油通过管道卷曲:看起来不像焦油档案

来自分类Dev

Ubuntu:这看起来不像tar存档

来自分类Dev

foreach看起来不像在php中正常工作

来自分类Dev

为什么我的TCP数据包看起来不像协议分析器的TCP数据包?

来自分类Dev

为什么GHC类型检查器不像看起来几乎相同的两个函数之一?

来自分类Dev

python对象实例变量看起来像一个类变量?

来自分类Dev

Windows C ++-在类中创建窗口使它看起来异常

来自分类Dev

为什么静态嵌套类看起来有实例字段?

来自分类Dev

如何使按钮看起来像标签?

来自分类Dev

如何使UITableView看起来像这样?

来自分类Dev

如何使Matlab图形看起来更好

来自分类Dev

如何使我的网址看起来更好?

来自分类Dev

如何使QTabWidget看起来透明?

来自分类Dev

如何使jQuery动画看起来平滑?

来自分类Dev

如何查询看起来很团结的字典?

来自分类Dev

如何使UITableView看起来像这样?

来自分类Dev

如何使我的网址看起来更好?

来自分类Dev

如何使角色看起来像在移动?

来自分类Dev

如何使uitextfield看起来像在塌陷?

来自分类Dev

在较高的层次上,期望序列图中的类的界面看起来像类图中的对应物是合理的吗?

来自分类Dev

Google Map,如何使其看起来更亮?看起来有点暗

来自分类Dev

CSS线性渐变看起来不像Photoshop一样,可以固定吗?

Related 相关文章

  1. 1

    如何制作看起来不像按钮的Glyphicon按钮

  2. 2

    Django:看起来不像模块路径

  3. 3

    CSV文件看起来不像表格

  4. 4

    我的iPhone模拟器看起来不像其他人的

  5. 5

    无业游民的触发器并不像看起来那样简单

  6. 6

    Cloud Ubuntu 服务器(Ubuntu 16.04) tar:这看起来不像 tar 存档

  7. 7

    如何制作一个其构造函数看起来像内置类的构造函数的类?

  8. 8

    焦油通过管道卷曲:看起来不像焦油档案

  9. 9

    Ubuntu:这看起来不像tar存档

  10. 10

    foreach看起来不像在php中正常工作

  11. 11

    为什么我的TCP数据包看起来不像协议分析器的TCP数据包?

  12. 12

    为什么GHC类型检查器不像看起来几乎相同的两个函数之一?

  13. 13

    python对象实例变量看起来像一个类变量?

  14. 14

    Windows C ++-在类中创建窗口使它看起来异常

  15. 15

    为什么静态嵌套类看起来有实例字段?

  16. 16

    如何使按钮看起来像标签?

  17. 17

    如何使UITableView看起来像这样?

  18. 18

    如何使Matlab图形看起来更好

  19. 19

    如何使我的网址看起来更好?

  20. 20

    如何使QTabWidget看起来透明?

  21. 21

    如何使jQuery动画看起来平滑?

  22. 22

    如何查询看起来很团结的字典?

  23. 23

    如何使UITableView看起来像这样?

  24. 24

    如何使我的网址看起来更好?

  25. 25

    如何使角色看起来像在移动?

  26. 26

    如何使uitextfield看起来像在塌陷?

  27. 27

    在较高的层次上,期望序列图中的类的界面看起来像类图中的对应物是合理的吗?

  28. 28

    Google Map,如何使其看起来更亮?看起来有点暗

  29. 29

    CSS线性渐变看起来不像Photoshop一样,可以固定吗?

热门标签

归档