如何实现兼容std::vector与std::set的C++ range通用插入方法
问题解答
核心结论
可以使用同一段通用代码实现向vector和set中插入元素,只需要修正原代码的参数错误并使用兼容的插入接口即可。
原代码问题梳理
首先原代码存在两个明显错误:
Insert方法的Range range参数是值传递,传入的容器会被拷贝,函数内的修改完全不会作用到外部的原容器,需要改为左值引用Range& rangemain函数存在笔误:p.Insert(set, 5);应为p1.Insert(set, 5);,p是适配vector的Processor实例,无法接收set类型参数
Insert方法正确实现
这里提供两种可行的实现方案:
方案1:极简通用实现(仅适配vector/set场景)
利用两种容器都支持的insert(迭代器位置, 值)接口实现,仅需一行代码:
void Insert(Range& range, T val) { range.insert(std::ranges::end(range), val); }
- 对
vector而言,insert(end(), val)等价于push_back(val),会将元素追加到容器末尾 - 对
set而言,传入的end()是插入位置提示,即使提示位置不符合排序规则,set也会自动找到正确位置插入,语法和功能完全兼容
方案2:编译期分支实现(通用全容器适配+性能最优)
如果需要适配更多容器类型,同时保留对应容器的最优插入性能,可以使用C++20的概念(Concept)做编译期判断,自动选择最优插入方式:
#include <ranges> #include <vector> #include <set> #include <type_traits> // 定义概念:检测容器是否支持push_back接口 template<typename Container, typename Val> concept has_push_back = requires(Container& c, Val&& v) { c.push_back(std::forward<Val>(v)); }; template <std::ranges::range Range> class Processor { public: using T = std::ranges::range_value_t<Range>; void Insert(Range& range, T val) { if constexpr (has_push_back<Range, T>) { // 对vector、list等支持push_back的容器调用性能更高的push_back range.push_back(val); } else { // 对set、map等关联容器调用insert接口 range.insert(val); } } }; int main() { std::vector<int> v; Processor<std::vector<int>> p; p.Insert(v, 5); // 自动调用push_back std::set<int> set; Processor<std::set<int>> p1; p1.Insert(set, 5); // 自动调用insert return 0; }
内容的提问来源于stack exchange,提问作者Alexey Starinsky
相关产品推荐
相关产品推荐

