You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ ranges:切换至filter_view时调用size()报错,transform_view正常

为什么filter_view不能调用size(),而transform_view可以?

错误原因

C++20引入的Ranges库中,视图是否支持size()取决于它是否满足Sized Range概念:

  • transform_view只是对原range的每个元素做转换,不会改变元素数量,因此继承了原range(这里是iota_view)的Sized属性,能直接返回原range的大小,所以可以调用size()。
  • filter_view是根据过滤条件筛选元素,过滤后的元素数量无法在O(1)时间内确定(必须遍历所有元素才能统计符合条件的数量),因此它不属于Sized Range,既没有size()成员函数,也不支持operator[](无法通过索引直接定位元素)。

你代码里的output.size()和output[i]在使用filter时报错,本质都是因为filter_view不支持Sized和Random Access特性。

解决方法

方法1:使用范围for循环(推荐,符合Ranges设计理念)

直接遍历视图元素,不需要依赖size和索引:

#include <iostream>
#include <ranges>
#include <sstream>

int main()
{
    using namespace std;
    auto input = views::iota(1, 5 + 1);

    auto output = input |
                  views::filter([](auto n) { return n % 2 == 0; });

    stringstream ss;
    ss << "[";
    bool first = true;
    for (auto num : output)
    {
        if (!first)
            ss << ',';
        ss << num;
        first = false;
    }
    ss << "]";
    cout << ss.str();
    return 0;
}

方法2:将视图转换为容器(如果需要频繁使用size或索引)

把filter后的视图转成vector这类支持size和随机访问的容器:

#include <iostream>
#include <ranges>
#include <sstream>
#include <vector>

int main()
{
    using namespace std;
    auto input = views::iota(1, 5 + 1);

    auto output = input |
                  views::filter([](auto n) { return n % 2 == 0; });
    vector<int> filtered(output.begin(), output.end()); // 转换为vector

    stringstream ss;
    ss << "[";
    for (auto i = 0; i < filtered.size() - 1; ++i)
    {
        ss << filtered[i] << ',';
    }
    ss << filtered[filtered.size() - 1];
    ss << "]";
    cout << ss.str();
    return 0;
}

方法3:手动计算size(不推荐,效率低)

如果一定要保留原有循环结构,可以先遍历一遍视图统计元素数量,但会导致两次遍历,效率不高:

#include <iostream>
#include <ranges>
#include <sstream>
#include <iterator>

int main()
{
    using namespace std;
    auto input = views::iota(1, 5 + 1);

    auto output = input |
                  views::filter([](auto n) { return n % 2 == 0; });

    // 手动计算size
    auto size = distance(output.begin(), output.end());

    stringstream ss;
    ss << "[";
    auto it = output.begin();
    for (auto i = 0; i < size - 1; ++i)
    {
        ss << *it << ',';
        ++it;
    }
    if (size > 0)
        ss << *it;
    ss << "]";
    cout << ss.str();
    return 0;
}

内容的提问来源于stack exchange,提问作者D G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:52:29