C++中能否无需模板实现可变参函数调用并隔离executor代码?
解决方案:把Executor模板改成非模板实现(用std::function等工具)
核心就是用**std::function<void()>**做类型擦除,把各种不同签名的函数统一包装成无参可调用对象,这样Executor就不需要模板,可以单独放到cpp文件编译,彻底解决重复编译和代码隔离的问题。
具体实现步骤
1. 编写非模板的Executor类(头文件)
把原来的模板Executor改成只处理std::function<void()>的普通类,头文件里只放声明,实现放到单独cpp:
// executor.h #pragma once #include <vector> #include <functional> class Executor { public: // 添加任务:接受任意可被包装成std::function<void()>的对象 void add_task(std::function<void()> task); // 执行所有任务 void execute_all(); private: std::vector<std::function<void()>> tasks_; };
2. 实现Executor的逻辑(cpp文件)
这部分代码只会编译一次,以后修改也只需要重新编译这个文件:
// executor.cpp #include "executor.h" void Executor::add_task(std::function<void()> task) { tasks_.push_back(std::move(task)); } void Executor::execute_all() { for (auto& task : tasks_) { task(); } tasks_.clear(); }
3. 用std::bind/std::mem_fn适配不同签名的函数
不管是普通函数、成员函数还是带参数的函数,都能通过绑定转成符合要求的std::function<void()>:
// main.cpp #include "executor.h" #include <iostream> #include <functional> // 普通无参函数 void plain_func() { std::cout << "Plain function called\n"; } // 带参数的普通函数 void func_with_args(int a, const std::string& b) { std::cout << "Func with args: " << a << ", " << b << "\n"; } // 类和成员函数 class MyClass { public: void member_func() { std::cout << "Member function called\n"; } void member_with_args(double x) { std::cout << "Member with arg: " << x << "\n"; } }; int main() { Executor exec; // 添加普通无参函数 exec.add_task(plain_func); // 用std::bind绑定带参数的函数 exec.add_task(std::bind(func_with_args, 42, "hello")); MyClass obj; // 用std::mem_fn绑定成员函数(也可以直接用std::bind) exec.add_task(std::bind(std::mem_fn(&MyClass::member_func), &obj)); // 绑定带参数的成员函数 exec.add_task(std::bind(&MyClass::member_with_args, &obj, 3.14)); // 执行所有任务 exec.execute_all(); return 0; }
为什么这么做能解决你的问题
- 编译时间减少:Executor的实现只编译一次,调用方代码编译时不需要实例化模板,避免了模板代码在每个调用点重复编译的开销。
- 代码隔离:Executor的实现细节都在cpp文件里,头文件只暴露接口,调用方看不到内部逻辑,耦合度更低。
- 灵活性保留:借助
std::bind和std::mem_fn,依然能处理几乎所有类型的可调用对象,和原来的模板版本功能一致。
内容的提问来源于stack exchange,提问作者Damir Tenishev
相关产品推荐
相关产品推荐

