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

如何用std::function适配参数不同的函数作为入参?

解决方案

方案1:使用模板函数

利用C模板特性,让compute接受任意可调用对象,通过编译期判断来匹配对应签名的调用逻辑(C17及以上支持if constexpr):

#include <optional>
#include <type_traits>

void first_function(double z) {
    // 实现
}

void second_function(double x, double y, double z) {
    // 实现
}

template<typename Func>
void compute(Func func, std::optional<double> x, std::optional<double> y, double z) {
    if (x.has_value() && y.has_value()) {
        if constexpr (std::is_invocable_v<Func, double, double, double>) {
            func(x.value(), y.value(), z);
        }
    } else {
        if constexpr (std::is_invocable_v<Func, double>) {
            func(z);
        }
    }
}

// 调用示例
int main() {
    compute(first_function, std::nullopt, std::nullopt, 3.14);
    compute(second_function, 1.0, 2.0, 3.14);
    return 0;
}

该方案无需额外包装,原生函数、lambda、函数对象都能直接支持,编译期确定调用逻辑,无运行时开销。

方案2:重载compute函数

针对两种函数签名分别实现重载版本,逻辑最直观:

#include <optional>

void first_function(double z) {
    // 实现
}

void second_function(double x, double y, double z) {
    // 实现
}

// 适配单参数函数的重载
void compute(void (*func)(double), std::optional<double>, std::optional<double>, double z) {
    func(z);
}

// 适配三参数函数的重载
void compute(void (*func)(double, double, double), std::optional<double> x, std::optional<double> y, double z) {
    if (x.has_value() && y.has_value()) {
        func(x.value(), y.value(), z);
    }
    // 可根据需求补充x/y无值时的处理逻辑
}

// 调用示例
int main() {
    compute(first_function, std::nullopt, std::nullopt, 3.14);
    compute(second_function, 1.0, 2.0, 3.14);
    return 0;
}

此方案无模板或变体的复杂性,编译期直接匹配重载,性能最优,适合仅需支持这两种特定签名的场景。

方案3:使用std::variant存储多签名函数

如果需要运行时动态切换函数类型,可通过std::variant包装两种std::function:

#include <optional>
#include <functional>
#include <variant>

void first_function(double z) {
    // 实现
}

void second_function(double x, double y, double z) {
    // 实现
}

using FuncVariant = std::variant<std::function<void(double)>, std::function<void(double, double, double)>>;

void compute(FuncVariant func_var, std::optional<double> x, std::optional<double> y, double z) {
    if (x.has_value() && y.has_value()) {
        std::visit([&](auto&& func) {
            using FuncType = std::decay_t<decltype(func)>;
            if constexpr (std::is_same_v<FuncType, std::function<void(double, double, double)>>) {
                func(x.value(), y.value(), z);
            }
        }, func_var);
    } else {
        std::visit([&](auto&& func) {
            using FuncType = std::decay_t<decltype(func)>;
            if constexpr (std::is_same_v<FuncType, std::function<void(double)>>) {
                func(z);
            }
        }, func_var);
    }
}

// 调用示例
int main() {
    compute(std::function<void(double)>(first_function), std::nullopt, std::nullopt, 3.14);
    compute(std::function<void(double, double, double)>(second_function), 1.0, 2.0, 3.14);
    return 0;
}

该方案适合运行时动态选择函数的场景,但会存在一定运行时开销。


内容的提问来源于stack exchange,提问作者structuralengin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 15:08:11