c++ 变平的增压范围适配器

o2rvlv0m  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(155)

我知道如何写flattening iterator,但我如何用升压范围适配器做同样的事情?
我想让这个工作:

  1. vector<vector<int>> input({{1, 2}, {3, 4}});
  2. vector<int> result;
  3. boost::copy(input | flattened, back_inserter(result));
  4. // result is now {1, 2, 3, 4}

我看过Method 3,但我不够聪明,不知道如何应用它。

6rvt4ljy

6rvt4ljy1#

这似乎可以工作(基于Flattening iterator)。

  1. #include <boost/range/adaptors.hpp>
  2. #include <boost/range/iterator_range.hpp>
  3. template <typename OuterIterator> class flattening_iterator
  4. {
  5. public:
  6. using outer_iterator = OuterIterator;
  7. using inner_iterator = typename OuterIterator::value_type::iterator;
  8. using iterator_category = std::forward_iterator_tag;
  9. using value_type = typename std::iterator_traits<inner_iterator>::value_type;
  10. using difference_type = typename std::iterator_traits<inner_iterator>::difference_type;
  11. using pointer = typename std::iterator_traits<inner_iterator>::pointer;
  12. using reference = typename std::iterator_traits<inner_iterator>::reference;
  13. flattening_iterator()
  14. {
  15. }
  16. flattening_iterator(outer_iterator it)
  17. : outer_it_(it)
  18. , outer_end_(it)
  19. {
  20. }
  21. flattening_iterator(outer_iterator it, outer_iterator end)
  22. : outer_it_(it)
  23. , outer_end_(end)
  24. {
  25. if (outer_it_ == outer_end_)
  26. {
  27. return;
  28. }
  29. inner_it_ = outer_it_->begin();
  30. advance_past_empty_inner_containers();
  31. }
  32. reference operator*() const
  33. {
  34. return *inner_it_;
  35. }
  36. pointer operator->() const
  37. {
  38. return &*inner_it_;
  39. }
  40. flattening_iterator& operator++()
  41. {
  42. ++inner_it_;
  43. if (inner_it_ == outer_it_->end())
  44. advance_past_empty_inner_containers();
  45. return *this;
  46. }
  47. flattening_iterator operator++(int)
  48. {
  49. flattening_iterator it(*this);
  50. ++*this;
  51. return it;
  52. }
  53. friend bool operator==(const flattening_iterator& a, const flattening_iterator& b)
  54. {
  55. if (a.outer_it_ != b.outer_it_)
  56. return false;
  57. if (a.outer_it_ != a.outer_end_ &&
  58. b.outer_it_ != b.outer_end_ &&
  59. a.inner_it_ != b.inner_it_)
  60. return false;
  61. return true;
  62. }
  63. friend bool operator!=(const flattening_iterator& a, const flattening_iterator& b)
  64. {
  65. return !(a == b);
  66. }
  67. private:
  68. void advance_past_empty_inner_containers()
  69. {
  70. while (outer_it_ != outer_end_ && inner_it_ == outer_it_->end())
  71. {
  72. ++outer_it_;
  73. if (outer_it_ != outer_end_)
  74. inner_it_ = outer_it_->begin();
  75. }
  76. }
  77. outer_iterator outer_it_;
  78. outer_iterator outer_end_;
  79. inner_iterator inner_it_;
  80. };
  81. template <typename Iterator> flattening_iterator<Iterator> flatten(Iterator it)
  82. {
  83. return flattening_iterator<Iterator>(it, it);
  84. }
  85. template <typename Iterator> flattening_iterator<Iterator> flatten(Iterator first, Iterator last)
  86. {
  87. return flattening_iterator<Iterator>(first, last);
  88. }
  89. template <typename R>
  90. struct flat_range
  91. : boost::iterator_range<flattening_iterator<typename boost::range_iterator<R>::type>>
  92. {
  93. public:
  94. using iterator = flattening_iterator<typename boost::range_iterator<R>::type>;
  95. private:
  96. using base = boost::iterator_range<iterator>;
  97. public:
  98. flat_range(R& r)
  99. : base(iterator(boost::begin(r), boost::end(r)), iterator(boost::end(r)))
  100. {
  101. }
  102. };
  103. namespace detail
  104. {
  105. struct flat_forwarder
  106. {
  107. };
  108. };
  109. template <class R> inline flat_range<R> operator|(R&& r, detail::flat_forwarder)
  110. {
  111. BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<R>));
  112. return flat_range<R>(r);
  113. }
  114. template <class R> inline flat_range<const R> operator|(const R& r, detail::flat_forwarder)
  115. {
  116. BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<const R>));
  117. return flat_range<const R>(r);
  118. }
  119. namespace
  120. {
  121. const detail::flat_forwarder flattened{};
  122. }

可以这样使用:

  1. vector<vector<int>> input{{1, 2}, {3, 4}};
  2. ostringstream o;
  3. boost::copy(input | flattened, std::ostream_iterator<int>(o, " "));
展开查看全部

相关问题