如何用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
相关产品推荐
相关产品推荐

