Пусть rw = ranges::views
.
Пытаюсь создать исключительно с помощью range-v3
аналог конструкции:
std::vector<int> v;
// range = {0, 1, 2}
auto range = rw::ints (0, 3);
for (int i : range)
for (int j : range)
v.push_back (func (i, j))
// v = {func (0, 0), func (0, 1), func (0, 2),
// func (1, 0), func (1, 1), func (1, 2),
// func (2, 0), func (2, 1), func (2, 2)}
Я попробовал следующий вариант:
// range = {0, 1, 2}
auto range = rw::ints (0, 3);
// range_of_ranges = {{func (0, 0), func (0, 1), func (0, 2)},
// {func (1, 0), func (1, 1), func (1, 2)},
// {func (2, 0), func (2, 1), func (2, 2)}}
auto range_of_ranges = rw::transform (range, [] (int i) {
return rw::transform (range, [i] (int j) { return func (i, j); });
});
// result = {func (0, 0), func (0, 1), func (0, 2),
// func (1, 0), func (1, 1), func (1, 2),
// func (2, 0), func (2, 1), func (2, 2)}
auto result = rw::concat (range, range, range);
for (auto x : result)
printf ("%d\n", x);
Но если я заменю
// result = {func (0, 0), func (0, 1), func (0, 2),
// func (1, 0), func (1, 1), func (1, 2),
// func (2, 0), func (2, 1), func (2, 2)}
auto result = rw::concat (range, range, range);
с
// result = { {{func (0, 0), func (0, 1), func (0, 2)},
// {func (1, 0), func (1, 1), func (1, 2)},
// {func (2, 0), func (2, 1), func (2, 2)}} }
auto result = rw::concat (range_of_ranges);
будет предупреждение компилятора:
warning: format specifies type 'int' but the argument has type 'ranges::iota_view<int, int>' [-Wformat]
printf ("%d\n", x);
К сожалению, это не работает, и я не очень понимаю, как это исправить. Я понимаю, что функция concat должна принимать свои аргументы и объединять их в диапазон, и я только что создал диапазон длиной 1, но я не знаю, какое решение будет правильным. Не могли бы вы дать мне подсказку?
UPD[1] (на основе комментария Jarod42: range-v3
имеет views::cartesian_product
): оказалось, упростите код до следующего:
auto range = rw::ints (0, 3);
auto cart_prod = rw::cartesian_product (range, range);
auto unpack_args_and_call_func = [] (const auto &arg) {
return std::apply (func, arg);
};
auto result = rw::transform (cart_prod, unpack_args_and_call_func);
Однако использование аргумента распаковки выглядит не очень красиво и удобно.
UPD[2] (на основе комментария Jarod42: есть также views::join
для вашего range_of_ranges
): Заменять
// result = {func (0, 0), func (0, 1), func (0, 2),
// func (1, 0), func (1, 1), func (1, 2),
// func (2, 0), func (2, 1), func (2, 2)}
auto result = rw::concat (range, range, range);
с
// result = { {{func (0, 0), func (0, 1), func (0, 2)},
// {func (1, 0), func (1, 1), func (1, 2)},
// {func (2, 0), func (2, 1), func (2, 2)}} }
auto result = rw::join (range_of_ranges);
views::cartesian_product
- person Jarod42   schedule 21.05.2021views::join
для вашегоrange_of_ranges
. - person Jarod42   schedule 21.05.2021transform
. - person Jarod42   schedule 21.05.2021