我试图做的转换在carpet产品,平整的边缘在年底。我收到的结果whish不是一个范围,这是问题:
#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;
}
字符串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:
型
我做错了什么?
更新:当我试图将edges
传递给一个函数时,问题发生了,该函数将const reference
接收到input_range
。
1条答案
按热度按时间1l5u6lss1#
让我稍微重新检查你的支票,使事情更清楚:
字符串
这里的问题是,
join
视图 * 有时 * 不是const
-iterable的-这取决于你加入的范围的类型。特别是,join
对输入范围的范围进行操作不会是const-iterable的,因为结果视图必须缓存状态-即使在begin()
中-这意味着我们不能将其视为可变的。这里可能引起混淆的原因是
edges.cbegin()
实际上可以工作,只是在本例中它实际上并不意味着std::as_const(edges).begin()
(在这里不会编译)。相反,cbegin()
现在总是存在于范围适配器上,并可靠地返回一个实际常量迭代器。在这里,edges
本身是一个引用类型为Edge&
的范围,因此edges.cbegin()
为您提供了一个引用类型为Edge const&
的迭代器。