fork download
  1. #include <iostream> // for std::cout
  2. #include <iterator> // for std::ostream_iterator
  3. #include <tuple> // for std::tie
  4. #include <type_traits> // for std::enable_if
  5. #include <vector> // for std::vector
  6.  
  7. template<typename T>
  8. struct identity { using type = T; };
  9.  
  10. template<typename Integral, Integral... N>
  11. struct integer_sequence {
  12.  
  13. template<Integral Offset>
  14. struct offset : identity<integer_sequence<Integral, (N + Offset)...>> { };
  15. };
  16.  
  17. namespace detail {
  18.  
  19. template<typename... T>
  20. void ignore(T&&...) { }
  21.  
  22. template<std::size_t Idx, typename... T>
  23. inline auto nth_arg(T&&... arg)
  24. -> decltype(std::get<Idx>(std::tie(arg...))) {
  25. return std::get<Idx>(std::tie(arg...));
  26. }
  27.  
  28. template<std::size_t N, std::size_t... T>
  29. struct gen_iter_indices
  30. : gen_iter_indices<(N - 2), (N - 2), T...> { };
  31. template<std::size_t... T>
  32. struct gen_iter_indices<0, T...>
  33. : identity<integer_sequence<std::size_t, T...>> { };
  34.  
  35. template<
  36. typename... Iterator,
  37. typename Integral,
  38. Integral... Begin,
  39. Integral... End
  40. >
  41. inline static bool eq_n(const std::tuple<Iterator...>& iters,
  42. integer_sequence<Integral, Begin...>,
  43. integer_sequence<Integral, End...>)
  44. {
  45. const bool res[] { (std::get<Begin>(iters) == std::get<End>(iters))... };
  46. for(std::size_t i = 0; i < sizeof...(Begin); ++i) {
  47. if(res[i]) { return true; }
  48. }
  49. return false;
  50. }
  51.  
  52. template<typename... Iterator, typename Integral, Integral... Begin>
  53. inline static void increment_n(const std::tuple<Iterator...>& iters,
  54. integer_sequence<Integral, Begin...>)
  55. {
  56. ignore(++std::get<Begin>(iters)...);
  57. }
  58.  
  59. template<
  60. typename NaryOperation,
  61. typename... Iterator,
  62. typename Integral,
  63. Integral... Begin
  64. >
  65. inline auto call_n(const std::tuple<Iterator...>& iters,
  66. NaryOperation op,
  67. integer_sequence<Integral, Begin...>)
  68. -> decltype(op(*std::get<Begin>(iters)...))
  69. {
  70. return op(*std::get<Begin>(iters)...);
  71. }
  72. }
  73.  
  74. template<
  75. typename OutputIter,
  76. typename NaryOperation,
  77. typename... InputIter,
  78. typename = typename std::enable_if<
  79. (2 <= sizeof...(InputIter)) && // Atleast one iterator pair
  80. (0 == (sizeof...(InputIter) % 2)) // and multiple of two
  81. >::type
  82. >
  83. static OutputIter transform_n(OutputIter out_iter,
  84. NaryOperation op,
  85. InputIter... in_iter)
  86. {
  87. using begins = typename detail::gen_iter_indices<sizeof...(InputIter)>::type;
  88. using ends = typename begins::template offset<1>::type;
  89.  
  90. const auto iters = std::tie(in_iter...); // tuple of references to iterators
  91.  
  92. while(!detail::eq_n(iters, begins{}, ends{})) {
  93. *out_iter = detail::call_n(iters, op, begins{});
  94. ++out_iter;
  95. detail::increment_n(iters, begins{});
  96. }
  97.  
  98. return out_iter;
  99. }
  100.  
  101. int main(int argc, char** argv) {
  102. std::vector<int> v1 { 1, 2, 3 };
  103. std::vector<int> v2 { 4, 5, 6 };
  104. std::vector<int> v3 { 7, 8, 9 };
  105. std::vector<int> res { };
  106. res.resize(3);
  107. auto end = transform_n(
  108. res.begin(),
  109. [](int _1, int _2, int _3) { return _1 + _2 + _3; },
  110. v1.begin(),
  111. v1.end(),
  112. v2.begin(),
  113. v2.end(),
  114. v3.begin(),
  115. v3.end()
  116. );
  117. std::copy(res.begin(), end, std::ostream_iterator<int>(std::cout, " "));
  118. return 0;
  119. }
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
12 15 18