fork(4) download
  1. #include <tuple> // make_tuple, tuple
  2. #include <utility> // pair
  3. #include <vector> // vector
  4. #include <iostream>
  5. #include <string>
  6. #include <ios>
  7.  
  8. namespace detail {
  9.  
  10. // the lambda is fully bound with one element from each of the ranges
  11. template<class Op>
  12. void insert_tuples(Op op)
  13. {
  14. // evaluating the lambda will insert the currently bound tuple
  15. op();
  16. }
  17.  
  18. // "peal off" the first range from the remaining tuple of ranges
  19. template<class Op, class InputIterator1, class... InputIterator2>
  20. void insert_tuples(Op op, std::pair<InputIterator1, InputIterator1> head, std::pair<InputIterator2, InputIterator2>... tail)
  21. {
  22. // "peal off" the elements from the first of the remaining ranges
  23. // NOTE: the recursion will effectively generate the multiple nested for-loops
  24. for (auto it = head.first; it != head.second; ++it) {
  25. // bind the first free variable in the lambda, and
  26. // keep one free variable for each of the remaining ranges
  27. detail::insert_tuples(
  28. [=](InputIterator2... elems) mutable { op(it, elems...); },
  29. tail...
  30. );
  31. }
  32. }
  33.  
  34. } // namespace detail
  35.  
  36. // convert a tuple of ranges to the range of tuples representing the Cartesian product
  37. template<class OutputIterator, class... InputIterator>
  38. void cartesian_product(OutputIterator result, std::pair<InputIterator, InputIterator>... dimensions)
  39. {
  40. detail::insert_tuples(
  41. [=](InputIterator... elems) mutable { *result++ = std::make_tuple(*elems...); },
  42. dimensions...
  43. );
  44. }
  45.  
  46. int main()
  47. {
  48. bool b[] = { false, true };
  49. int i[] = { 0, 1 };
  50. std::string s[] = { "Hello", "World" };
  51.  
  52. std::vector< std::tuple<bool, int, std::string> > cp = {
  53. std::make_tuple(false, 0, "Hello") ,
  54. std::make_tuple(false, 0, "World"),
  55. std::make_tuple(false, 1, "Hello"),
  56. std::make_tuple(false, 1, "World"),
  57. std::make_tuple(true, 0, "Hello"),
  58. std::make_tuple(true, 0, "World"),
  59. std::make_tuple(true, 1, "Hello"),
  60. std::make_tuple(true, 1, "World")
  61. };
  62.  
  63. std::vector< std::tuple<bool, int, std::string> > result;
  64. cartesian_product(
  65. std::back_inserter(result),
  66. std::make_pair(std::begin(b), std::end(b)),
  67. std::make_pair(std::begin(i), std::end(i)),
  68. std::make_pair(std::begin(s), std::end(s))
  69. );
  70.  
  71. std::cout << std::boolalpha << (result==cp) << "\n";
  72.  
  73. // now use a single flat loop over result to do your own thing
  74. for (auto t: result) {
  75. std::cout << std::get<0>(t) << ", ";
  76. std::cout << std::get<1>(t) << ", ";
  77. std::cout << std::get<2>(t) << "\n";
  78. }
  79. }
Success #stdin #stdout 0s 3032KB
stdin
Standard input is empty
stdout
true
false, 0, Hello
false, 0, World
false, 1, Hello
false, 1, World
true, 0, Hello
true, 0, World
true, 1, Hello
true, 1, World