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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:51:01