C++怎么实现泛型算法_C++模板函数教程【复用】

7次阅读

泛型算法不能用std::function替代模板参数,因其带来运行时开销、擦除类型信息,导致无法推导重载函数/函数模板/带捕获Lambda,丧失constexpr和sfinae能力。

C++怎么实现泛型算法_C++模板函数教程【复用】

泛型算法为什么不能直接用 std::function 替代模板参数

因为 std::function 带运行时开销,且无法推导重载函数、函数模板或临时 lambda 的完整类型。泛型算法依赖编译期类型推导来适配任意可调用对象,而 std::function 会擦除类型信息,导致无法匹配重载、丢失 constexpr 能力,甚至让 SFINAE 失效。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 坚持用模板参数接收可调用对象,比如 template<typename f> void sort(..., F&& f)</typename>
  • 需要存储时才考虑 std::function,但别把它塞进泛型算法接口
  • 注意:lambda 捕获列表为空时可隐式转成函数指针,但带捕获的 lambda 无法转,强行转会编译失败

auto 参数和模板参数在 c++20 里到底怎么选

C++20 允许写 void algo(auto x, auto y),看起来更短,但它本质是“简写模板”,每个 auto 独立推导类型,不保证一致;而显式模板参数(如 template<typename t> void algo(T x, T y)</typename>)能强制类型统一,支持特化和约束。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 要类型一致(比如两个参数必须同为 int 或同为 double),用显式模板参数 + static_assertrequires
  • 只做简单转发、不关心类型关系时,auto 参数够用,但别指望它帮你做概念检查
  • 混合使用风险高:比如 void f(auto x, template<typename t> T y)</typename> 是非法的,C++ 不允许混用两种语法

泛型算法里怎么安全处理迭代器失效问题

泛型算法本身不负责内存管理,但用户传入的容器迭代器可能因算法内部操作(比如 eraseresize)失效。标准库算法如 std::sortstd::transform 不修改容器结构,所以安全;但你自己写的泛型算法如果调用了非 const 成员函数,就得格外小心。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 默认假设传入的迭代器来自 const 容器视图,避免在算法内调用 vec.push_back() 这类操作
  • 如果真要修改容器,明确要求传入容器引用而非迭代器,并文档注明“此算法可能导致迭代器失效”
  • 测试时故意用 std::vectorstd::list 对比:前者随机访问快但插入易失效,后者插入稳定但不支持 + 运算符

为什么 std::invoke 在泛型算法里几乎必用

因为用户传来的可调用对象可能是普通函数、成员函数指针、成员变量指针、绑定对象的 std::bind 结果,甚至带 operator() 的类。不用 std::invoke 就得写一 if constexpr 分支去适配,极易漏 case。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 所有泛型算法中涉及“调用用户传入的可调用对象”的地方,一律用 std::invoke(f, args...)
  • 注意:std::invoke 要求头文件 <functional></functional>,别忘了 include
  • 别自己手写 f(args...) —— 面对 &MyClass::member 这种,编译直接报错,错误信息还特别长

泛型算法最难的不是写出来,而是想清楚“谁负责生命周期、谁承担类型约束、谁决定失效边界”。这些细节不会报错,但会在某个深夜调试时突然咬你一口。

text=ZqhQzanResources