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

能否使用std::ranges::split_view搭配可比较但非同源类型的分隔符?

关于用std::views::split实现按任意空白符拆分char范围的问题

结论是:没法直接用std::views::split实现这种需求,但可以通过组合标准库的其他视图来达到同样效果,或者换用更适配的工具。

原因

std::views::split的核心逻辑是匹配固定的分隔符序列——它需要你提供一个明确的范围(比如单个字符、字符串)作为分隔符,然后在原范围里找完全匹配这个序列的位置来拆分。而“按任意空白符拆分”是基于单个字符是否满足空白条件的谓词逻辑,和split的设计初衷不匹配,自然没法直接用自定义的Whitespace结构体作为分隔符。

替代实现方案

方案1:用group_by + filter直接拆分(推荐)

这种方式直接针对“连续空白视为单个分隔”的需求,一步到位:

#include <ranges>
#include <string>
#include <cctype>
#include <iostream>

int main() {
    std::string s = "hello   world\tfoo\nbar";
    // 先按"是否同为空白/非空白"分组,再过滤掉空白组
    auto split_result = s
        | std::views::group_by([](char a, char b) {
            return std::isspace(static_cast<unsigned char>(a)) == std::isspace(static_cast<unsigned char>(b));
        })
        | std::views::filter([](auto&& group) {
            return !std::isspace(static_cast<unsigned char>(*group.begin()));
        });

    // 遍历输出拆分结果
    for (auto&& part : split_result) {
        std::cout << std::string(part) << "\n";
    }
}

这个方案不需要预处理,效率也更高,完全符合“按任意空白符拆分,连续空白算一个”的需求。

方案2:预处理后再用split(凑合用)

如果非要依赖std::views::split,可以先把所有空白字符统一成同一个(比如空格),再压缩连续的空格为单个,最后用split(' ')拆分,还要过滤掉空的子范围:

#include <ranges>
#include <string>
#include <cctype>
#include <iostream>

int main() {
    std::string s = "hello   world\tfoo\nbar";
    // 第一步:把所有空白转成空格
    auto normalized = s
        | std::views::transform([](char c) {
            return std::isspace(static_cast<unsigned char>(c)) ? ' ' : c;
        })
        // 第二步:压缩连续空格为单个
        | std::views::group_by([](char a, char b) { return a == b; })
        | std::views::transform([](auto&& group) { return *group.begin(); });

    // 第三步:用空格拆分,再过滤空范围
    auto split_result = normalized 
        | std::views::split(' ')
        | std::views::filter([](auto&& part) { return !part.empty(); });

    for (auto&& part : split_result) {
        std::cout << std::string(part) << "\n";
    }
}

这种方式步骤冗余,不如方案1高效,只是满足了“用split”的形式需求。

方案3:C++23的views::tokenize(更适配)

如果你的编译器支持C++23,可以用std::views::tokenize,它专门支持基于谓词的拆分:

#include <ranges>
#include <string>
#include <cctype>
#include <iostream>

int main() {
    std::string s = "hello   world\tfoo\nbar";
    // 提取所有非空白的连续字符序列
    auto split_result = s | std::views::tokenize([](char c) {
        return !std::isspace(static_cast<unsigned char>(c));
    });

    for (auto&& part : split_result) {
        std::cout << std::string(part) << "\n";
    }
}

这个工具的设计就是用来处理“按规则提取 token”的场景,完美匹配你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:35:09