连接向量范围并没有给出范围

Гео*_*нов 1 c++ gcc std-ranges c++23

我正在尝试对笛卡尔积进行变换,最终使边缘变平。我收到的结果不是范围,这就是问题所在:

#include <ranges>
#include <vector>
#include <iostream>
#include <tuple>
#include <iterator>

int main() {
    auto indicies = std::views::iota(0, 3);

    auto coords = std::views::cartesian_product(indicies, indicies);

    auto edges = coords | std::views::transform([](const auto& coord) {
        using Coord = std::pair<std::size_t, std::size_t>;
        using Edge = std::pair<Coord, Coord>;
        std::vector<Edge> ret;
        const auto& [x, y] = coord;
        auto curr = Coord{x, y};
        if (x + 1 < 3) {
            auto dest = Coord{x + 1, y};
            ret.emplace_back(curr, dest);
        }
        if (y + 1 < 3) {
            auto dest = Coord{x, y + 1};
            ret.emplace_back(curr, dest);
        }
        return ret;
    }) | std::views::join;

    std::cout << edges.cbegin()->first.first << std::endl;

    // static_assert(std::ranges::input_range<const decltype(edges)>);//  <- does not compile with message that ;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

的输出g++-13如下(static_assert未注释时):

<source>: In function 'int main()':
<source>:31:32: error: static assertion failed
   31 |     static_assert(std::ranges::input_range<const decltype(edges)>);//  <- does not compile with message that ;
      |                   ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:31:32: note: constraints not satisfied
In file included from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/string_view:48,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/basic_string.h:47,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/string:54,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/locale_classes.h:40,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/ios_base.h:41,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/streambuf:43,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/streambuf_iterator.h:35,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/iterator:66,
                 from /opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/ranges:43,
                 from <source>:1:
/opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/ranges_base.h:501:13:   required for the satisfaction of 'range<_Tp>' [with _Tp = const std::ranges::join_view<std::ranges::transform_view<std::ranges::cartesian_product_view<std::ranges::iota_view<int, int>, std::ranges::iota_view<int, int> >, main::._anon_155> >]
/opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/ranges_base.h:501:21:   in requirements with '_Tp& __t' [with _Tp = const std::ranges::join_view<std::ranges::transform_view<std::ranges::cartesian_product_view<std::ranges::iota_view<int, int>, std::ranges::iota_view<int, int> >, main::._anon_155> >]
/opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/ranges_base.h:503:22: note: the required expression 'std::ranges::__cust::begin(__t)' is invalid
  503 |         ranges::begin(__t);
      |         ~~~~~~~~~~~~~^~~~~
/opt/compiler-explorer/arm/gcc-13.2.0/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/include/c++/13.2.0/bits/ranges_base.h:504:20: note: the required expression 'std::ranges::__cust::end(__t)' is invalid
  504 |         ranges::end(__t);
      |         ~~~~~~~~~~~^~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
Compiler returned:
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

edges更新:当我尝试传递给一个函数时,出现了问题,该函数接收const reference到一个input_range.

Bar*_*rry 5

让我稍微重新拼写一下你的支票,让事情变得更清楚:

using E = decltype(edges);
static_assert(std::ranges::input_range<E>);       // ok
static_assert(std::ranges::input_range<E const>); // error
Run Code Online (Sandbox Code Playgroud)

这里的问题是视图有时join是不可迭代的 - 这取决于您要加入的范围类型。特别是,输入范围的范围不会是常量迭代的,因为结果视图必须缓存状态——即使是——这意味着我们不能以可变的方式进行迭代。constjoinbegin()

这里可能造成混淆的原因是它edges.cbegin()确实有效,只是在这种情况下它实际上并不意味着std::as_const(edges).begin()(这里不会编译)。相反,cbegin()现在总是存在于范围适配器上,并可靠地返回一个实际常量迭代器。这里,edges它本身是一个引用类型为 的范围,Edge&因此edges.cbegin()为您提供了一个引用类型为 的迭代器Edge const&