C++如何实现仅获取函数除首个预定义参数外的其余参数类型
问题原因
你修改后的代码编译失败主要有两个核心问题:
- 特化匹配范围过窄:仅覆盖了第一个参数为
int的const成员函数、以及第一个参数为int的函数指针场景,缺少非const成员函数、第一个参数非int的函数等场景的匹配逻辑,不匹配的场景会触发主模板的无限递归继承,最终编译报错。 - 逻辑耦合度过高:把“过滤第一个参数”的逻辑直接写到函数类型萃取的特化里,既容易触发匹配错误,也不便于后续扩展修改。
解决方案
推荐先保留通用的全参数萃取逻辑,单独实现tuple切片工具来提取第一个参数之后的类型,解耦逻辑更稳定:
完整实现代码
#include <tuple> #include <type_traits> // 通用函数参数萃取:获取所有参数类型 template <typename T> struct FuncTraits : FuncTraits<decltype(&T::operator())> {}; // 特化const成员函数 template <typename C, typename R, typename... Args> struct FuncTraits<R(C::*)(Args...) const> : FuncTraits<R(*)(Args...)> {}; // 特化非const成员函数(覆盖非常量lambda等场景) template <typename C, typename R, typename... Args> struct FuncTraits<R(C::*)(Args...)> : FuncTraits<R(*)(Args...)> {}; // 特化普通函数指针 template <typename R, typename... Args> struct FuncTraits<R(*)(Args...)> { // 参数总数 static constexpr std::size_t total_arg_count = sizeof...(Args); // 所有参数的tuple类型 using all_args = std::tuple<std::decay_t<Args>...>; }; // 工具模板:去掉tuple第一个元素 template <typename Tuple> struct pop_first_arg; template <typename First, typename... Rest> struct pop_first_arg<std::tuple<First, Rest...>> { // 如果你需要限定第一个参数必须是int,解开下面这行注释即可 // static_assert(std::is_same_v<std::decay_t<First>, int>, "第一个参数必须为int类型"); static constexpr std::size_t rest_arg_count = sizeof...(Rest); using type = std::tuple<Rest...>; }; // 对外快捷别名,直接传入函数类型即可拿到第一个参数之后的类型 template <typename T> using rest_args_t = typename pop_first_arg<typename FuncTraits<T>::all_args>::type; template <typename T> constexpr std::size_t rest_arg_count_v = pop_first_arg<typename FuncTraits<T>::all_args>::rest_arg_count;
使用示例
#include <string> // 测试普通函数 void demo(int a, float b, std::string c) {} static_assert(std::is_same_v<rest_args_t<decltype(demo)>, std::tuple<float, std::string>>); static_assert(rest_arg_count_v<decltype(demo)> == 2); // 测试lambda auto lambda = [](double x, bool y, int z) { return 0; }; static_assert(std::is_same_v<rest_args_t<decltype(lambda)>, std::tuple<bool, int>>); static_assert(rest_arg_count_v<decltype(lambda)> == 2);
内容的提问来源于stack exchange,提问作者user16540664
相关产品推荐
相关产品推荐

