Range-v3: 如何在std::map容器中正确使用actions::insert接口
ranges::actions::insert 适配std::map的正确用法
错误原因
你遇到的编译报错是因为ranges::actions::insert的参数使用不符合函数签名要求:该action的第三个参数不是元素转换函数,仅支持传入待插入的单个元素或迭代器范围,你直接传入转换lambda自然找不到匹配的重载。
正确的处理逻辑应该是:先通过views系列接口完成元素的筛选、转换操作,再将处理完成的元素范围通过管道传给insert,插入到目标map中。
修正后的实现代码
#include "https://raw.githubusercontent.com/HowardHinnant/date/master/include/date/date.h" #include <chrono> #include <fmt/format.h> #include <iostream> #include <limits> #include <map> #include <range/v3/all.hpp> struct pivot_t { double price; double s; unsigned int d; std::chrono::system_clock::time_point timestamp; pivot_t() : price(0.0), s(0.0), d(0){}; pivot_t(const double price, const double s, const unsigned int d, const std::chrono::system_clock::time_point timestamp) : price(price), s(s), d(d), timestamp(timestamp){}; }; auto main() -> int { using namespace date; using namespace std::chrono; using namespace std::chrono_literals; // 仅作为参考时间点使用 const auto tp_now = std::chrono::system_clock::from_time_t(0); const auto m = std::map<system_clock::time_point, pivot_t>{ {tp_now + 0min, {1.1, 1.11, 0, tp_now + 0min}}, {tp_now + 1min, {2.2, 2.22, 0, tp_now + 1min}}, {tp_now + 2min, {3.3, 3.33, 0, tp_now + 3min}}, {tp_now + 3min, {4.4, 4.44, 0, tp_now + 3min}}, {tp_now + 4min, {3.3, 3.33, 0, tp_now + 4min}}, {tp_now + 5min, {4.4, 4.44, 0, tp_now + 5min}}, {tp_now + 6min, {7.7, 7.77, 0, tp_now + 6min}}, {tp_now + 7min, {8.8, 8.88, 0, tp_now + 7min}}, {tp_now + 8min, {9.9, 9.99, 0, tp_now + 8min}}, {tp_now + 9min, {10.10, 10.1010, 0, tp_now + 9min}}, {tp_now + 10min, {11.11, 11.1111, 0, tp_now + 10min}}, {tp_now + 11min, {12.12, 12.1212, 0, tp_now + 11min}}, {tp_now + 12min, {13.13, 13.1313, 0, tp_now + 12min}}, {tp_now + 13min, {14.14, 14.1414, 0, tp_now + 13min}}}; auto r = std::map<system_clock::time_point, pivot_t>{}; auto push_r = [](const auto& elem) { return std::make_pair(elem.first, pivot_t{elem.second.price, elem.second.s, elem.second.d, elem.first}); }; // 完整的管道调用:筛选→转换→插入 auto& v = m // 这里替换为你自己的筛选逻辑,不需要筛选可直接移除这一步 | ranges::views::filter([](const auto& elem) { return elem.second.price > 3.0; }) | ranges::views::transform(push_r) | ranges::actions::insert(r, r.end()); for(const auto& i : v) std::cout << i.first << " = " << i.second.price << std::endl; return 0; }
实现说明
- 筛选逻辑:通过
ranges::views::filter传入你的条件lambda,只保留符合要求的元素 - 元素转换:通过
ranges::views::transform调用你写的转换逻辑,得到符合目标map类型要求的键值对 - 插入操作:
ranges::actions::insert会直接修改传入的目标mapr,将前面管道输出的所有元素插入到指定位置,返回值是r的引用。如果不需要额外的引用变量,也可以不接收返回值,直接遍历r即可。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

