boost :: any_range和operator []

时间:2014-11-23 10:53:24

标签: c++ boost stl boost-range

请考虑以下代码:

#include <boost/range.hpp>
#include <boost/range/any_range.hpp>
#include <boost/range/join.hpp>

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <list>

struct TestData {
  TestData() : m_strMem01("test"), m_intMem02(42), m_boolMem03(true) {}
  std::string m_strMem01;
  int m_intMem02;
  bool m_boolMem03;
};

struct IntComp {
  bool operator()(const TestData &s, int i) { return s.m_intMem02 < i; }
  bool operator()(int i, const TestData &s) { return i < s.m_intMem02; }
  bool operator()(const TestData &i, const TestData &s) {
    return i.m_intMem02 < s.m_intMem02;
  }
};
struct StrComp {
  bool operator()(const TestData &s, const std::string &str) {
    return s.m_strMem01 < str;
  }
  bool operator()(const std::string &str, const TestData &s) {
    return str < s.m_strMem01;
  }
  bool operator()(const TestData &i, const TestData &s) {
    return i.m_strMem01 < s.m_strMem01;
  }
};

typedef boost::any_range<TestData, boost::forward_traversal_tag,
                         const TestData &, std::ptrdiff_t> TestRange;

std::vector<TestData> vecData(10);
std::list<TestData> listData(20);

TestRange foo() {
  TestRange retVal;

  auto tmp1 = std::equal_range(vecData.cbegin(), vecData.cend(), 42, IntComp());
  retVal = boost::join(retVal, tmp1);
  auto tmp2 =
      std::equal_range(listData.cbegin(), listData.cend(), "test", StrComp());
  retVal = boost::join(retVal, tmp2);
  return retVal;
}

int main(int argc, char *argv[]) {
  auto res = foo();
  for (auto a : res) {
    std::cout << a.m_strMem01 << std::endl;
  }
  //std::cout << res[4].m_intMem02 << std::endl;
}

如果您取消注释最后一行,则代码会因distance_to未实现any_forward_iterator_interface而失败。我不确定我在这里错过了什么,比如实施operator[]distance_to但是为了什么?我自己的版本遍历标记?为什么它首先不起作用?

Coliru version

2 个答案:

答案 0 :(得分:2)

我想说答案取决于您在实现新迭代器抽象时的性能需求和懒惰。你的[]运算符不工作的核心原因是std :: list&lt; ...&gt;不提供随机访问遍历迭代器。如果你选择了一个提供这种迭代器的容器。你any_range&lt; ...&gt;可以采取random_access_traversal_tag,一切都会好的。 我认为可以公平地说,在列表顶部实现随机访问迭代器并不是一件大事,只需封装当前索引并在列表中向前和向后计数,只要特定位置是指被访问,但它明显违背了列表性能的性质。

  • 是否有充分的理由将其中一个集合保留在列表中?
  • 是否有充分理由通过随机访问生成的any_range?
  • 为std :: list?
  • 提供低效的随机访问接口是否值得

答案 1 :(得分:1)

当然any_iterator(它是any_range实现的基础)并没有无偿地模拟你传递的任何奇数迭代器的RandomAccess迭代器。

如果你想要这样做,只需制作一个迭代器适配器来实现这一点(使列表中的随机访问元素变得非常慢 - 所以不要这样做。)