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

如何用static_assert在编译期检查类可变参数大小一致?

编译期检查可变模板参数大小一致的正确实现

你的代码存在两个核心问题:

  1. 静态成员arg_reference_size无法在constexpr函数中完成赋值并用于编译期检查——静态变量的初始化/赋值属于运行期逻辑,而static_assert要求表达式必须是编译期常量表达式。
  2. 负责初始化参考大小的check_args_size函数从未被调用,size_is_equal一开始就使用未初始化的arg_reference_size,逻辑完全失效。

下面给出两种可行的实现方案:

方案一:递归模板特化(兼容C++11及以上)

这种方式不需要依赖额外标准库头文件,通过递归模板逐次检查相邻参数的大小是否一致:

#include <cstddef>

// 空参数包或单个参数时,默认返回true
template<typename... Args>
constexpr bool all_same_size() {
    return true;
}

// 多参数时:检查前两个参数大小相同,再递归检查剩余参数
template<typename First, typename Second, typename... Rest>
constexpr bool all_same_size() {
    return sizeof(First) == sizeof(Second) && all_same_size<Second, Rest...>();
}

template<typename... Args>
class MyClass {
    static_assert(all_same_size<Args...>(), "所有模板参数的大小必须一致");
};

// 测试示例
int main() {
    MyClass<int, int, long> err; // 编译报错:long与int大小不同
    MyClass<char, unsigned char, signed char> ok; // 编译通过,三者大小均为1
}

方案二:C++17折叠表达式(简洁高效)

利用C++17引入的折叠表达式,用一行代码完成所有参数与第一个参数的大小对比,代码更简洁:

#include <cstddef>
#include <tuple>
#include <type_traits>

template<typename... Args>
class MyClass {
    // 处理空参数包的情况,避免tuple_element访问越界
    static_assert(sizeof...(Args) == 0 || 
                  (... && (sizeof(Args) == sizeof(std::tuple_element_t<0, std::tuple<Args...>>))),
                  "所有模板参数的大小必须一致");
};

// 测试示例
int main() {
    MyClass<int, int, long> err; // 编译报错
    MyClass<double, double, double> ok; // 编译通过
}

这里用std::tuple_element_t取出第一个参数的类型,再通过折叠表达式(... && 条件)对所有参数逐一检查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:22:55