You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:56:06