C++17使用可变参数调用函数后输出剩余未使用参数的实现方法
C++17 实现combine函数方案
核心思路
- 先通过自定义类型萃取工具获取可调用对象
F的入参个数 - 借助
std::index_sequence拆分可变参数包,取出对应数量的参数传入std::invoke执行F - 剩余参数通过C++17折叠表达式批量输出到标准输出
完整实现代码
#include <iostream> #include <functional> #include <tuple> #include <type_traits> // 萃取可调用对象的参数个数 template <typename T> struct function_arity : function_arity<decltype(&T::operator())> {}; // 特化:普通函数指针 template <typename R, typename... Args> struct function_arity<R(*)(Args...)> : std::integral_constant<size_t, sizeof...(Args)> {}; // 特化:非const成员函数/仿函数operator() template <typename R, typename C, typename... Args> struct function_arity<R(C::*)(Args...)> : std::integral_constant<size_t, sizeof...(Args)> {}; // 特化:const成员函数/仿函数operator() template <typename R, typename C, typename... Args> struct function_arity<R(C::*)(Args...) const> : std::integral_constant<size_t, sizeof...(Args)> {}; template <typename T> constexpr size_t function_arity_v = function_arity<T>::value; // 辅助:调用f时传入前N个参数 template <size_t N, typename F, typename Tuple, size_t... Is> decltype(auto) invoke_first_n(F&& f, Tuple&& args, std::index_sequence<Is...>) { return std::invoke(std::forward<F>(f), std::get<Is>(std::forward<Tuple>(args))...); } // 辅助:输出第N位及之后的剩余参数 template <size_t N, typename Tuple, size_t... Is> void print_rest(Tuple&& args, std::index_sequence<Is...>) { ((std::cout << std::get<N + Is>(std::forward<Tuple>(args)) << " "), ...); } // 目标combine函数 template <class F, class ...Args> void combine(F&& f, Args&& ... args) { constexpr size_t arity = function_arity_v<std::decay_t<F>>; // 入参个数校验 static_assert(arity >= 1 && arity <= sizeof...(Args), "可调用对象F的入参数量必须在1到传入参数总数量之间"); auto args_tuple = std::forward_as_tuple(std::forward<Args>(args)...); // 执行F调用 invoke_first_n<arity>(std::forward<F>(f), args_tuple, std::make_index_sequence<arity>{}); // 输出剩余参数 if constexpr (arity < sizeof...(Args)) { print_rest<arity>(args_tuple, std::make_index_sequence<sizeof...(Args) - arity>{}); } std::cout << "\n"; }
注意事项
- 支持普通函数、函数指针、无重载的仿函数、lambda表达式的参数个数自动推导
- 若可调用对象存在重载的
operator()或模板化的operator(),无法自动推导参数个数,需要手动指定参数数量调整实现 - 参数输出默认用空格分隔,可根据需求调整
print_rest中的分隔符
测试用例
// 测试1:普通函数 void test_func(int a, double b) { std::cout << "func执行结果:" << a + b << " | 剩余参数:"; } // 测试2:lambda auto test_lambda = [](const std::string& s) { std::cout << "lambda执行结果:" << s << " | 剩余参数:"; }; int main() { combine(test_func, 10, 20.5, "test", 996); combine(test_lambda, "hello world", 3.1415, false); return 0; }
输出结果
func执行结果:30.5 | 剩余参数:test 996 lambda执行结果:hello world | 剩余参数:3.1415 0
内容的提问来源于stack exchange,提问作者Dewfy
相关产品推荐
相关产品推荐

