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

如何将std::pair<迭代器,迭代器>传入期望std::ranges::range的接口?

衔接std::pair迭代器对与C++20范围的方案

背景

C11中std::pair不支持基于范围的for循环,也未提供begin()/end()方法。到C20,尽管范围(ranges)支持大幅增强,但存储两个迭代器的std::pair依旧不满足std::ranges::range概念,无法直接用于std::ranges::for_each这类新范围API。std::ranges::subrange才是迭代器对表示范围的标准类型,但旧代码仍大量使用std::pair实现类似功能,需要衔接方案。

核心需求

  • 无需解构pair,可直接作为范围API的参数
  • 若pair来自函数调用,仅需调用一次(避免std::ranges::subrange(func().first, func().second)这种重复调用)
  • 语法尽可能简洁,优先STL内置方案,其次Boost或自行实现

解决方案

1. STL内置方案

方法1:用std::apply包装

std::apply可将pair的两个元素作为参数传递给subrange构造函数,且仅计算一次pair表达式:

#include <ranges>
#include <utility>
#include <algorithm>

// 示例旧函数:返回迭代器pair
std::pair<int*, int*> get_old_range(int* arr, size_t n) {
    return {arr, arr + n};
}

int main() {
    int arr[] = {1,2,3,4,5};
    // 仅调用一次get_old_range,直接传入pair表达式
    std::ranges::for_each(
        std::apply(std::ranges::subrange{}, get_old_range(arr, 5)),
        [](int x) { /* 处理逻辑 */ }
    );
}

依赖C++17的CTAD(类模板实参推导)可省略subrange的模板参数,语法更简洁。

方法2:结构化绑定+临时变量

允许临时变量的情况下,语法直观且仅调用一次函数:

auto [beg, end] = get_old_range(arr, 5);
std::ranges::for_each(std::ranges::subrange(beg, end), [](int x) { /* 处理逻辑 */ });

2. 自行实现方案

方法1:短名称转换函数

实现一个极简的转换函数,适配左值/右值pair:

#include <ranges>
#include <utility>

// 短名称函数(比如`sr`),快速转换pair为subrange
template <std::input_iterator Iter>
constexpr auto sr(const std::pair<Iter, Iter>& p) {
    return std::ranges::subrange(p.first, p.second);
}

template <std::input_iterator Iter>
constexpr auto sr(std::pair<Iter, Iter>&& p) {
    return std::ranges::subrange(std::move(p.first), std::move(p.second));
}

// 使用示例
std::ranges::for_each(sr(get_old_range(arr, 5)), [](int x) { /* 处理逻辑 */ });

方法2:自定义隐式转换包装类

通过包装类让特定std::pair隐式转为满足range概念的类型(注意:不要全局重载std::pair的转换,避免冲突):

#include <ranges>
#include <utility>

template <std::input_iterator Iter>
struct PairRange : std::ranges::subrange<Iter> {
    // 隐式构造接受pair
    constexpr PairRange(const std::pair<Iter, Iter>& p) 
        : std::ranges::subrange<Iter>(p.first, p.second) {}
    constexpr PairRange(std::pair<Iter, Iter>&& p) 
        : std::ranges::subrange<Iter>(std::move(p.first), std::move(p.second)) {}
};

// 模板推导指引
template <std::input_iterator Iter>
PairRange(std::pair<Iter, Iter>) -> PairRange<Iter>;

// 自定义接受range的函数
void process_range(std::ranges::input_range auto&& r) {
    std::ranges::for_each(r, [](int x) { /* 处理逻辑 */ });
}

// 使用示例:直接传入pair,隐式转换为PairRange
process_range(get_old_range(arr, 5));

3. Boost方案

Boost的boost::iterator_range支持直接从std::pair构造,语法简洁:

#include <boost/range/iterator_range.hpp>
#include <ranges>

// 使用示例
std::ranges::for_each(
    boost::make_iterator_range(get_old_range(arr, 5)),
    [](int x) { /* 处理逻辑 */ }
);

boost::make_iterator_range接受迭代器对(包括std::pair),返回满足范围概念的对象,且仅计算一次pair表达式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 14:04:51