为什么我不能通过 const 引用传递 std::views::join ?

问题描述 投票:0回答:1

我有下面的代码(也在编译器资源管理器上),我很困惑为什么

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;
}

c++ c++20 std-ranges
1个回答
0
投票

当您加入的嵌套范围的引用是pv范围时,

join_view
需要将整个pv范围临时存储到其内部成员中,这使得其
begin()
不具有
const
资格,因为迭代器将修改此缓存
join_view
的成员。

也就是说,在你的例子中

join_view
只有非
const
限定的begin(),这使得它的const对象不满足
range
概念。

© www.soinside.com 2019 - 2024. All rights reserved.