Guest User

Untitled

a guest
Dec 10th, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.85 KB | None | 0 0
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <vector>
  4. #include <algorithm>
  5.  
  6.  
  7. template <std::size_t N>
  8. bool increase(const std::array<std::size_t , N> & sizes,
  9. std::array<std::size_t, N> & indexes) {
  10. bool is_increased = false;
  11. //Создадим цикл, в котором переберем все возможные комбинации. Будем изменять индекс контейнера до момента, когда они закончатся. После этого обнулим индекс исходного контейнера, увеличивая индекс предыдущего. Так будем делать до тех пор, пока не будут перебраны все возможные комбинации. После того, как все возможные комбинации будут рассмотрены, функция вернет значение false.
  12. for(std::size_t i = 0; i < N; ++i) {
  13. const std::size_t index = N-1-i;
  14. ++indexes[index];
  15. if(indexes[index] >= sizes[index])
  16. indexes[index] = 0;
  17. else {
  18. is_increased = true;
  19. break;
  20. }
  21. }
  22.  
  23. return is_increased;
  24. }
  25.  
  26. template<typename F, std::size_t ... Indexes,
  27. std::size_t N, typename Tuple>
  28. void apply(F && function,
  29. //ссылка на rvalue: вместо глубокого копирования данных кучи, скопируем указатель, а затем установим исходный указатель на ноль. Это необходимо, чтобы реализовать перемещение без дублирования кода и издержек времени выполнения
  30. std::index_sequence<Indexes...>,
  31. //последовательность индексов
  32. const std::array<std::size_t, N> &indexes, //массив индексов
  33. const Tuple &tuple) //кортеж векторов из функции combine
  34. {
  35. function(std::get<Indexes>(tuple)[indexes[Indexes]]...);
  36. //вызывется лямбда функция, в которой происходит добавление нового элемента в конец контейнера result. Новый элемент - это кортеж, который является частичным прямым произведением с элементами контейнеров vs.., индексы которых достаются из контейнера indexes, который был построен в is_increased).
  37. }
  38.  
  39.  
  40. template<typename ... Types>
  41. auto combine(const std::vector<Types> &... vs) {
  42.  
  43. std::vector<std::tuple<Types...>> result; //создается контейнер с типом кортеж, типы которого равны исходным типам контейнеров vs...
  44.  
  45. constexpr std::size_t N = sizeof...(Types); //вычисляется количество исходных контейнеров
  46.  
  47. std::array<std::size_t, N> sizes = {vs.size()...};//создается массив, содержащий размеры исходных контейнеров
  48. std::array<std::size_t, N> indexes; //создается массив, содержащий индексы исходных контейнеров
  49. indexes.fill(0);
  50.  
  51.  
  52. //создаем цикл, который будет работать до тех пор, пока bool increase != false
  53. for (;increase(sizes, indexes) ;) {
  54. apply([&result](const auto &...args) { result.emplace_back(args...); },
  55. //лямбда-функция, которая в контейнер result добавляет( при помощи функции emplace_back() ) все возможные аргументы. В нашем случае, это будут кортежи, содержащие в себе частичное прямое произведение из всевозможных комбинаций индексов контейров vs...
  56. std::make_index_sequence<N>(),
  57. //создается последовательность индексов ( в compile time)
  58. indexes, std::tie(vs...)); //кортеж из всевозможных контейнеров vs...
  59. }
  60. return result;
  61.  
  62. }
  63.  
  64. // =============================================================================
  65.  
  66. int main(int argc, char **argv) {
  67.  
  68.  
  69. std::vector<int> v1 = {1, 2};
  70. std::vector<std::string> v2 = {" A ", " B ", " C "};
  71. std::vector<int> v3 = {4, 5, 6, 7};
  72.  
  73. const auto result = combine(v1, v2, v3);
  74.  
  75. for (const auto &t : result) {
  76. std::cout << '(' <<
  77. std::get<0>(t) << ' ' <<
  78. std::get<1>(t) << ' ' <<
  79. std::get<2>(t) << ')' << ',';
  80. }
  81. std::cout << std::endl;
  82.  
  83. system("pause");
  84. return 0;
  85. }
Add Comment
Please, Sign In to add comment