fork(2) download
  1.  
  2. #include <utility>
  3.  
  4. template <typename Iterator, typename Runnable>
  5. struct ConditionalIterator
  6. {
  7. private:
  8. Iterator iterator;
  9. Iterator end;
  10. const Runnable& condition;
  11. public:
  12. ConditionalIterator(Iterator b, Iterator e, const Runnable& r)
  13. :
  14. iterator(b),
  15. end(e),
  16. condition(r)
  17. {
  18. }
  19. auto operator*() -> decltype(*iterator)
  20. {
  21. return *iterator;
  22. }
  23. ConditionalIterator& operator++()
  24. {
  25. do
  26. {
  27. ++iterator;
  28. }
  29. while ( iterator != end && !condition(*iterator) );
  30. return *this;
  31. }
  32. bool operator==(const ConditionalIterator& second)
  33. {
  34. return iterator == second.iterator;
  35. }
  36. bool operator!=(const ConditionalIterator& second)
  37. {
  38. return !(*this == second);
  39. }
  40. };
  41.  
  42. template <typename Range, typename Runnable>
  43. struct ConditionalRange;
  44.  
  45. template <typename Range, typename Runnable>
  46. ConditionalRange<Range, Runnable> makeConditionalRange(Range& range, Runnable&& condition)
  47. {
  48. static_assert(std::is_same<decltype(condition(*std::declval<Range>().begin())), bool>::value, "Condition must return a boolean value.");
  49. return ConditionalRange<Range, Runnable>(range, std::forward<Runnable>(condition));
  50. }
  51.  
  52. template <typename Range, typename Runnable>
  53. struct ConditionalRange
  54. {
  55. public:
  56. friend ConditionalRange makeConditionalRange<>(Range&, Runnable&&);
  57. public:
  58. using iterator_type = ConditionalIterator<decltype(std::declval<Range>().begin()), Runnable>;
  59. iterator_type begin() const
  60. {
  61. auto b = range.begin();
  62. while ( b != range.end() && !condition(*b) )
  63. {
  64. ++b;
  65. }
  66. return ConditionalIterator<decltype(std::declval<Range>().begin()), Runnable>(b, range.end(), condition);
  67. }
  68. iterator_type end() const
  69. {
  70. return ConditionalIterator<decltype(std::declval<Range>().begin()), Runnable>(range.end(), range.end(), condition);
  71. }
  72. private:
  73. ConditionalRange(Range& range_, Runnable&& condition_)
  74. :
  75. range(range_),
  76. condition(std::forward<Runnable>(condition_))
  77. {
  78. }
  79. private:
  80. Range& range;
  81. Runnable condition;
  82. };
  83.  
  84. // user code begins here!
  85.  
  86. #include <iostream>
  87. #include <vector>
  88.  
  89. int main()
  90. {
  91. std::vector<int> ns{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  92. for ( const auto& n : makeConditionalRange(ns, [](int a) { return a % 2 == 0; }) )
  93. {
  94. std::cout << n << " ";
  95. }
  96. std::cout << "\n";
  97. for ( const auto& n : makeConditionalRange(ns, [](int a) { return a % 2 != 0; }) )
  98. {
  99. std::cout << n << " ";
  100. }
  101. std::cout << "\n";
  102. }
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
0 2 4 6 8 
1 3 5 7 9