Гео*_*нов 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.
让我稍微重新拼写一下你的支票,让事情变得更清楚:
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&。