fork(1) download
  1. #include <iostream>
  2. #include <vector>
  3. #include <memory>
  4. #include <list>
  5. using namespace std;
  6.  
  7. template <typename T>
  8. struct ref_or_copy
  9. {
  10. ref_or_copy(T&& rval)
  11. : storage(new T(std::move(rval)))
  12. , val(*storage) { }
  13. ref_or_copy(T& lval) : val(lval) { }
  14.  
  15. std::unique_ptr<T> storage;
  16. T& val;
  17. };
  18.  
  19. template <typename C1, typename C2>
  20. struct chain_obj_struct {
  21. ref_or_copy<std::remove_reference_t<C1>> c1;
  22. ref_or_copy<std::remove_reference_t<C2>> c2;
  23. struct iterator {
  24. decltype(std::begin(c1.val)) it1;
  25. decltype(std::begin(c1.val)) it1_end;
  26. decltype(std::begin(c2.val)) it2;
  27. bool in_first;
  28.  
  29. iterator& operator++() {
  30. if (in_first) {
  31. ++it1;
  32. if (it1 == it1_end) {
  33. in_first = false;
  34. }
  35. } else {
  36. ++it2;
  37. }
  38. return *this;
  39. }
  40.  
  41. typename std::conditional<
  42. std::is_const<std::remove_reference_t<decltype(*it1)>>::value,
  43. decltype(*it1),
  44. decltype(*it2)>::type
  45. operator*()
  46. {
  47. if (in_first) return *it1;
  48. return *it2;
  49. }
  50.  
  51. bool operator==(const iterator& i2) {
  52. if (in_first != i2.in_first) return false;
  53. if (in_first)
  54. return it1 == i2.it1;
  55. else
  56. return it2 == i2.it2;
  57. }
  58. bool operator!=(const iterator& i2) {
  59. return !this->operator==(i2);
  60. }
  61. };
  62.  
  63. iterator begin() {
  64. return iterator{std::begin(c1.val), std::end(c1.val), std::begin(c2.val), true};
  65. }
  66.  
  67. iterator end() {
  68. return iterator{std::end(c1.val), std::end(c1.val), std::end(c2.val), false};
  69. }
  70. };
  71.  
  72. template <typename C1, typename C2>
  73. chain_obj_struct<C1, C2> chain_obj(C1&& c1, C2&& c2) {
  74. return chain_obj_struct<C1, C2>{std::forward<C1>(c1), std::forward<C2>(c2)};
  75. }
  76.  
  77. template <typename C>
  78. auto chain_it(C&& c) { return std::forward<C>(c); }
  79.  
  80. template <typename C1, typename C2, typename... Cs>
  81. auto chain_it(C1&& c1, C2&& c2)
  82. {
  83. return chain_obj(std::forward<C1>(c1), std::forward<C2>(c2));
  84. }
  85.  
  86. template <typename C1, typename... Cs>
  87. auto chain_it(C1&& c1, Cs&&... cs)
  88. {
  89. return chain_obj(std::forward<C1>(c1), chain_it(std::forward<Cs>(cs)...));
  90. }
  91.  
  92.  
  93. int main() {
  94. vector<int> a = {1, 2, 3, 4};
  95. vector<int> b = {5, 6, 7, 8};
  96. list<int> c = {9, 9, 4};
  97. const auto& ca = a;
  98. const auto& cb = b;
  99. for (auto& i : chain_it(a, cb, ca, b, c)) {
  100. cout << i << " ";
  101. }
  102.  
  103. return 0;
  104. }
Success #stdin #stdout 0s 3460KB
stdin
Standard input is empty
stdout
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 9 4