我有下面的代码(也在编译器资源管理器上),我很困惑为什么
const Range &
版本不起作用。编译器抱怨 std::range::begin (和 end)不起作用。
这实际上是一个 XY 问题 所以我还要提到我是如何到达这里的: 我正在对范围适配器编写一些单元测试,并在 googletest 中编写了一个匹配器来比较两个范围:
MATCHER_P(RangeEq, value, "") { return std::ranges::equal(arg, value); }
这工作得很好,直到我找到一个返回连接的适配器。当我试图弄清楚这一点时,我意识到我似乎无法将范围视为
const&
,也许这与 googletest 匹配器中的问题相同。
#include <algorithm>
#include <iostream>
#include <ranges>
#include <string>
#include <vector>
template <std::ranges::range Range>
auto print1(std::ostream& out, Range&& range) {
out << '[';
auto begin = std::ranges::begin(std::forward<Range>(range));
auto end = std::ranges::end(std::forward<Range>(range));
if (begin != end) {
out << *begin;
++begin;
}
while (begin != end) {
out << ", " << *begin;
++begin;
}
out << ']' << std::endl;
}
template <std::ranges::range Range>
auto print2(std::ostream& out, const Range& range) {
out << '[';
auto begin = std::ranges::begin(range);
auto end = std::ranges::end(range);
if (begin != end) {
out << *begin;
++begin;
}
while (begin != end) {
out << ", " << *begin;
++begin;
}
out << ']' << std::endl;
}
template <std::ranges::range Lhs, std::ranges::range Rhs>
bool equal1(Lhs&& lhs, Rhs&& rhs) {
return std::ranges::equal(std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
}
template <std::ranges::range Lhs, std::ranges::range Rhs>
bool equal2(const Lhs& lhs, const Rhs& rhs) {
return std::ranges::equal(lhs, rhs);
}
int main() {
std::cout << std::boolalpha;
auto view = std::views::iota(0, 5) | std::views::transform([](auto num) {
return std::views::iota(0, num);
}) |
std::views::join;
print1(std::cout, view);
// print2(std::cout, view); // compile error, why?
auto nums = std::vector<int>{0, 0, 1, 0, 1, 2, 0, 1, 2, 3};
std::cout << equal1(view, nums) << std::endl;
// std::cout << equal2(view, nums) << std::endl; // compile error, why?
return 0;
}
当您加入的嵌套范围的引用是pv范围时,
join_view
需要将整个pv范围临时存储到其内部成员中,这使得其begin()
不具有const
资格,因为迭代器将修改此缓存join_view
的成员。
也就是说,在你的例子中
join_view
只有非const
限定的begin(),这使得它的const对象不满足range
概念。