如何用static_assert在编译期检查类可变参数大小一致?
编译期检查可变模板参数大小一致的正确实现
你的代码存在两个核心问题:
- 静态成员
arg_reference_size无法在constexpr函数中完成赋值并用于编译期检查——静态变量的初始化/赋值属于运行期逻辑,而static_assert要求表达式必须是编译期常量表达式。 - 负责初始化参考大小的
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
相关产品推荐
相关产品推荐

