微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

2 个范围的所有组合的迭代器

如何解决2 个范围的所有组合的迭代器

是否可以使用 boost::iterators 库来创建显示 2 个范围组合结果的迭代器?请注意,为了使用,我们需要输出是迭代器。我们也不期望首先手动创建所有组合的向量。 (注:我们用C++17编译)

一个人为的例子:

auto v = std::vector<int>({1,2,3});
auto s = std::set<double>({0.5,1.5});
auto range = combineElements(v.begin(),v.end(),s.begin(),s.end(),[](int i,double d){ return std::pair{i,d}; });
for (auto [i,d] : range)
   std::cout << std::to_string(i) << ',' <<std::to_string(d) << ";";
// Expected output: 1,0.5;1,1.5;2,0.5;2,1.5;3,0.5;3,1.5;

我检查了 boost::iterators 的文档并发现:

  • Zip:这将第一个范围的第 n 个元素与第二个范围的第 n 个元素组合在一起。但是,不会将第 n 个元素与第 m 个元素组合在一起。
  • 生成器:需要提供的生成器可以手动记账 6 个迭代器:两个范围的开始、结束和当前。但是,它没有办法阻止它。
  • 函数输入:与生成器类似,我们可以将这些迭代器置于状态中,并使用结束迭代器为结束迭代器创建结束状态。但是,状态并未提供给生成器来计算迭代器的值。
  • 排列:适用于单个范围
  • 转换:适用于单一范围

我认为在这种情况下唯一的选择是手工编写客户迭代器是否正确?

解决方法

我认为在这种情况下唯一的选择是手工编写客户迭代器是否正确?

几乎是的。您可能希望将其分解为一个迭代器适配器,该适配器对每个元素重复 N 次,以及一个重复整个范围 M 次的迭代器适配器,这将允许您zip 一对。

template <class Iterator>
class repeat_iterator
  : public boost::iterator::iterator_adaptor< repeat_iterator<Iterator>,Iterator > 
{
  typedef boost::iterator::iterator_adaptor< repeat_iterator<Iterator>,Iterator > super_t;
  friend class boost::iterator::iterator_core_access;
  size_t len = 1;
  size_t curr = 0;

public:
  repeat_iterator() {}

  explicit repeat_iterator(Iterator x,size_t len,curr = 0)
      : super_t(x),len(len),curr(curr) {}

private:
  void increment() { 
      if (++curr == len) { 
          curr = 0;
          ++base_reference(); 
      }
  }
  void decrement() {
      if (curr-- == 0) {
          curr = len - 1;
          --base_reference(); 
      } 
  }
  void advance(typename super_t::difference_type n)
  {
      n += curr;
      base_reference() += n / len;
      curr = n % len;
  }
  template <class OtherIterator>
  typename super_t::difference_type
  distance_to(unstride_iterator<OtherIterator> const& y) const
  {
      return ((base() - y.base()) * len) + (curr - y.curr);
  }
};

template <class Iterator>
class cycle_iterator
  : public boost::iterator::iterator_adaptor< cycle_iterator<Iterator>,Iterator > 
{
  typedef boost::iterator::iterator_adaptor< cycle_iterator<Iterator>,Iterator > super_t;
  friend class boost::iterator::iterator_core_access;
  Iterator first;
  Iterator last;

public:
  cycle_iterator() {}

  explicit cycle_iterator(Iterator first,Iterator last)
      : super_t(first),first(first),last(last) {}

private:
  void increment() { 
      if (++base_reference() == last) { 
          base_reference() = first; 
      }
  }
  void decrement() {
      if (base_reference() == first) {
          base_reference() = last - 1; 
      } 
  }
  void advance(typename super_t::difference_type n)
  {
      n += std::distance(first,base_reference());
      n %= std::distance(first,last);
      base_reference() = first + n;
  }
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。