如何编写支持任意可调用类型的C++11函数包装器?
支持任意可调用类型的ModifyFunction实现(C++11)
原代码的问题在于模板参数仅针对std::function设计,编译器无法从lambda、函数指针等其他可调用类型自动推导出R和Args...参数。要支持任意可调用类型,我们可以通过自定义模板包装器实现,避免依赖std::function的类型约束。
解决方案:自定义模板包装器
这种方式无需手动推导可调用对象的签名,直接通过模板类封装原对象,同时保留其调用语义:
#include <utility> template<typename F> class ModifiedFunctionWrapper { private: F m_func; public: // 构造函数,用移动语义避免不必要的拷贝 explicit ModifiedFunctionWrapper(F func) : m_func(std::move(func)) {} // 重载调用运算符,支持任意参数转发 template<typename... Args> auto operator()(Args&&... args) -> decltype(m_func(std::forward<Args>(args)...)) { // 此处添加你的额外操作,例如日志打印、参数校验等 // std::cout << "Executing pre-operation..." << std::endl; // 转发参数并调用原函数 return m_func(std::forward<Args>(args)...); } }; // 工厂函数,推导传入的可调用对象类型并返回包装器实例 template<typename F> ModifiedFunctionWrapper<F> ModifyFunction(F f) { return ModifiedFunctionWrapper<F>(std::move(f)); }
测试示例
以下代码验证了不同可调用类型的兼容性:
#include <iostream> #include <functional> void PlainFunction() { std::cout << "Plain function called" << std::endl; } int main() { // 测试无参lambda auto modified_lambda = ModifyFunction([] { std::cout << "Lambda called" << std::endl; }); modified_lambda(); // 测试带参数lambda auto modified_add = ModifyFunction([](int a, int b) { return a + b; }); std::cout << "3 + 5 = " << modified_add(3, 5) << std::endl; // 测试std::function std::function<void()> func_obj([] { std::cout << "std::function called" << std::endl; }); auto modified_func = ModifyFunction(func_obj); modified_func(); // 测试普通函数指针 auto modified_plain = ModifyFunction(PlainFunction); modified_plain(); return 0; }
方案原理
- 模板类
ModifiedFunctionWrapper针对每个传入的可调用类型F生成特化版本,完美适配不同的调用签名。 - 调用运算符
operator()使用可变参数模板和std::forward实现完美转发,保留原函数的参数传递语义(左值/右值)。 - 通过
decltype推导返回类型,确保返回值与原函数一致,符合C++11的类型推导规则。
内容的提问来源于stack exchange,提问作者Gils
相关产品推荐
相关产品推荐

