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

C++如何从宏的可变参数中获取对应的类型参数包?

解决方案

问题核心原因

  • C++ 标准不存在 decltype...(可变参数) 语法,你的原有写法不符合语法规则
  • 直接写 decltype(__VA_ARGS__) 时,__VA_ARGS__ 内部的逗号会被识别为逗号运算符,最终仅返回最后一个参数的类型,无法得到完整的类型参数包

最优实现方案

利用函数模板的自动类型推导能力实现需求,不需要参数满足 constexpr 要求,也不需要修改原有 myFunctionHelper 逻辑:

template<std::size_t N, class T, class... Ts>
constexpr bool myFunctionHelper(const char (&fmt)[N], std::size_t n);

// 仅修改myFunction签名,增加的参数包仅用于推导类型,不会读取参数值
template <std::size_t N, typename... Ts>
constexpr bool myFunction(const char (&fmt)[N], Ts&&...) {
  return myFunctionHelper<N, Ts...>(fmt, 0);
}

#define FNC(fmt, ...)                                                       \
  do {                                                                      \
    /* ##__VA_ARGS__用于兼容无可变参数传入的场景 */                            \
    static_assert(myFunction(fmt, ##__VA_ARGS__),                           \
                  "Incorrect arg types");                                   \
  } while (false)

方案说明

  • 调用 myFunction 时编译器会自动根据传入的参数推导 Ts... 类型包,完全匹配你需要的所有参数类型
  • 因为 myFunction 内部没有访问参数包的任何值,仅用到编译期确定的类型信息,所以即使传入的参数不是 constexpr,整个表达式依然是合法的常量表达式,可以正常用于 static_assert
  • 兼容你原有 myFunctionHelper 的全部校验逻辑,不需要做额外修改

不修改原有myFunction签名的替代方案

如果你不想改动原有 myFunction 的定义,可以用类型列表萃取的方式实现:

// 原有代码保持不变
template<std::size_t N, class T, class... Ts>
constexpr bool myFunctionHelper(const char (&fmt)[N], std::size_t n);

template <std::size_t N, typename... Ts>
constexpr bool myFunction(const char (&fmt)[N]) {
  return myFunctionHelper<N, Ts...>(fmt, 0);
}

// 新增辅助逻辑
template <typename... Ts> struct TypeList {};

// 从参数包提取类型生成TypeList,仅用于类型推导
template <typename... Ts>
constexpr TypeList<Ts...> MakeTypeList(Ts&&...) { return {}; }

// 特化实现类型包展开
template <std::size_t N, typename T>
struct DispatchMyFunction;

template <std::size_t N, typename... Ts>
struct DispatchMyFunction<N, TypeList<Ts...>> {
  static constexpr bool Exec(const char (&fmt)[N]) {
    return myFunction<N, Ts...>(fmt);
  }
};

// 宏定义
#define FNC(fmt, ...)                                                       \
  do {                                                                      \
    static_assert(DispatchMyFunction<sizeof(fmt), decltype(MakeTypeList(__VA_ARGS__))>::Exec(fmt), \
                  "Incorrect arg types");                                   \
  } while (false)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:27:01