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

如何用range-v3实现类似ranges::to<T>()的可管道化函数适配multi_linestring

问题解答

一、通用问题:为ranges::to<T>()不支持的类实现类似功能

要让自定义类或第三方库类支持类似ranges::to<T>()的管道化转换,有两种核心方案:

1. 让目标类适配range-v3的容器概念

range-v3的to<T>要求目标类满足Container概念,核心要求包括:

  • 支持默认构造、拷贝/移动构造
  • 提供begin()/end()返回合法迭代器
  • 支持元素插入(如push_back()、insert())或范围构造
  • 可选:支持reserve()/resize()优化性能

如果目标类(如Boost.Geometry的multi_linestring)原生不满足,可以:

  • 为类添加必要的成员函数(如果有权限修改)
  • 特化range-v3的range::container_traits,手动适配容器接口

2. 实现自定义管道化适配器

如果无法修改目标类,可手动实现一个函数对象,通过重载operator|使其支持管道调用,模仿ranges::to的使用方式。核心步骤:

  • 定义一个函数对象,接收range并转换为目标类型
  • 重载operator|,让range视图可以通过管道传递给这个函数对象

二、具体场景:管道化构造Boost.Geometry的multi_linestring

错误原因

ranges::to<polylines>编译失败,是因为Boost.Geometry的multi_linestring没有满足range-v3对容器的全部适配要求,导致to无法自动推导如何从transform_view构造目标容器。

解决方案:将临时函数改造为可管道化适配器

把你现有的to_polylines函数模板,改造成支持管道调用的函数对象:

#include <range/v3/range.hpp>
#include <range/v3/view/transform.hpp>

namespace r = ranges;
namespace rv = ranges::views;
namespace bg = boost::geometry;

using point = bg::model::point<double, 2, bg::cs::cartesian>;
using polyline = bg::model::linestring<point>;
using polylines = bg::model::multi_linestring<polyline>;

// 定义可管道化的转换函数对象
struct to_polylines_fn {
    template <typename Rng>
    polylines operator()(Rng&& rng) const {
        polylines polys;
        // 用reserve替代resize,避免默认构造元素,提升效率
        polys.reserve(r::distance(rng));
        for (auto&& line : rng) {
            polys.push_back(std::forward<decltype(line)>(line));
        }
        return polys;
    }

    // 重载|运算符,支持管道调用
    template <typename Rng>
    friend auto operator|(Rng&& rng, to_polylines_fn) {
        return to_polylines_fn{}(std::forward<Rng>(rng));
    }
};

// 全局实例,直接用于管道
inline constexpr to_polylines_fn to_polylines{};

int main() {
    std::vector<point> some_points = { {1,1},{2,2},{3,3},{4,4},{5,5} };
    auto poly = some_points | r::to<polyline>();

    std::vector<std::vector<point>> vec_of_vec_of_pts = {
        {{1,1},{2,2},{3,3},{4,4},{5,5}},
        {{6,6},{7,7},{8,8}},
        {{9,9},{10,10},{11,11},{12,12}}
    };

    // 现在可以正常使用管道调用
    auto polys = vec_of_vec_of_pts 
               | rv::transform([](const auto& v) { return v | r::to<polyline>(); })
               | to_polylines;

    return 0;
}

简化写法(用range-v3宏)

如果使用range-v3的宏,可以更简洁地生成适配器:

#include <range/v3/view/adaptor.hpp>

// 用宏自动生成适配器和管道支持
RANGES_ADAPTOR_FUNCTION(to_polylines, to_polylines_fn, 1)

这样无需手动重载operator|,宏会自动处理闭包和管道逻辑。


原错误信息

1>[...]: error C2678: binary '|': no operator found which takes a left-hand operand of type 'ranges::transform_view<ranges::ref_view<std::vector<std::vector<point,std::allocator<point>>,std::allocator<std::vector<point,std::allocator<point>>>>>,Arg>' (or there is no acceptable conversion)
1>        with
1>        [
1>            Arg=main::<lambda_1>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include\cstddef(42,27): message : could be 'std::byte std::operator |(const std::byte,const std::byte) noexcept' [found using argument-dependent lookup]
1>C:\libraries\range-v3\include\range\v3\view\any_view.hpp(66,24): message : or       'ranges::category ranges::operator |(ranges::category,ranges::category) noexcept' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include\regex(1191,1): message : or       'std::_Node_flags std::operator |(std::_Node_flags,std::_Node_flags) noexcept' [found using argument-dependent lookup]
1>[...]: message : while trying to match the argument list '(ranges::transform_view<ranges::ref_view<std::vector<std::vector<point,std::allocator<point>>,std::allocator<std::vector<point,std::allocator<point>>>>>,Arg>, ranges::detail::to_container::closure<meta::id<polylines>,ranges::detail::to_container::fn<meta::id<polylines>>>)' 
1>        with
1>        [
1>            Arg=main::<lambda_1>
1>        ]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:15:47