将范围的范围连接到范围

Concatenate range of ranges to range

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-v3views::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 评论:您的 range_of_ranges 也有 views::join: 替换

// 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);

感谢Jarod42

// 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::join (range_of_ranges);

for (auto x : result)
    printf ("%d\n", x);