如何将static_assert与sizeof和stringify结合起来?
问题描述:
在我的应用程序中,内存使用情况非常关键。因此,我有特定的断言,在编译时检查内存大小,如果大小与我们之前认为正确的大小不同,则给出static_assert。如何将static_assert与sizeof和stringify结合起来?
我已经定义一个宏是这样的:
#define CHECKMEM(mytype, size) static_assert((sizeof(objectType) == size)), "Size incorrect for " #mytype "!");
这个宏使得它很容易写:
CHECKMEM(Book,144);
CHECKMEM(Library,80);
的问题是,当这个static_assert熄灭,这可能是十分很难找出新的大小应该是什么(例如通过使用隐藏的编译器选项“/ d1 reportAllClassLayout”)。 如果我可以包含实际尺寸,将会更方便:
Book的尺寸不正确!
它会使
尺寸不正确的书! (预期144,大小为152)
我试着写是这样的:
#define CHECKMEM(mytype, size) static_assert((sizeof(objectType) == size)), "Size incorrect for " #mytype "! (expected" #size ", size is " #sizeof(mytype) ")");
但你不能使用stringize(#)运算符的函数调用。
我也尝试添加双stringize伎俩,就像这样:
#define STR1(x) #x
#define STR2(x) STR1(x)
#define CHECKMEM(mytype, size) static_assert((sizeof(objectType) == size)), "Size incorrect for " #mytype "! (expected" #size ", size is " STR2(sizeof(mytype)) ")");
但不是打印size is 152
它打印size is sizeof(Book)
。
有没有办法在static_assert中对sizeof的结果进行字符串化?
答
我会使用调度上的功能模板做检查:
#include <cstddef>
template <typename ToCheck, std::size_t ExpectedSize, std::size_t RealSize = sizeof(ToCheck)>
void check_size() {
static_assert(ExpectedSize == RealSize, "Size is off!");
}
struct foo
{
char bla[16];
};
int main()
{
check_size<foo, 8>();
return 0;
}
结果:
In instantiation of ‘void check_size() [with ToCheck = foo; long unsigned int ExpectedSize = 8ul; long unsigned int RealSize = 16ul]’:
bla.cpp:15:22: required from here
bla.cpp:5:1: error: static assertion failed: Size is off!
的调试信息是在后面追踪的模板参数。
如果这真的是更好的,你将不得不决定,它也取决于编译器。它还使您能够使用模板地图隐藏预期的大小,总结出最大尺寸和其他奇特的事物。
答
取决于你的编译器,模板可能能够帮助:
template<int s, int t> struct check_size {
static_assert(s == t, "wrong size");
};
check_size<2+2, 5> doubleplusungood;
GCC输出:
prog.cpp: In instantiation of 'check_size<4, 5>':
prog.cpp:5:20: instantiated from here
prog.cpp:2:3: error: static assertion failed: "wrong size"
答
当你发现,该问题是在这里(另见本very similar question):
#define CHECKMEM(mytype, size) #sizeof(mytype)
这是不可能的,因为字符串化是由prep rocessor和sizeof在编译过程中进行评估。
请注意'sizeof'不是函数调用 – 2012-07-17 16:13:34
问题是'static_assert'的第二个参数必须是字符串文字,并且您不能在预处理器中构建它,因为您不能在其中使用sizeof 。 – pmr 2012-07-17 16:27:05