【发布时间】:2015-11-07 12:57:47
【问题描述】:
如果结构/类有一些填充,有没有办法(特征左右)来检测?
我不需要跨平台或标准化的解决方案,我在 MSVC2013 中需要它。
我可以检查一下
namespace A
{
struct Foo
{
int a;
bool b;
};
}
#pragma pack(push, 1)
namespace B
{
struct Foo
{
int a;
bool b;
};
}
#pragma pack(pop)
static const bool has_padding = sizeof(A::Foo) != sizeof(B::Foo);
但 C++ 不允许(据我所知)生成这种非侵入式(不触及现有结构)
理想情况下,我想从事这样的工作
template <typename T>
struct has_padding_impl
{
typedef __declspec(align(1)) struct T AllignedT;
};
template <typename T>
struct has_padding : typename std::conditional<sizeof(typename has_padding_impl<T>::AllignedT) == sizeof(T),
std::false_type,
std::true_type>::type{};
编辑 - 我为什么需要这个?
我正在使用现有的序列化系统,它存储了一些结构,只是将void* 传递给它们(在通用函数内部)并存储sizeof(T) 字节数......这样的二进制文件在我们的目标平台上是不可移植的, 由于使用了不同的编译器,因此无法保证如何插入填充。如果我可以静态检测所有带有填充的结构 T,我可以强制用户手动插入填充(一些控制填充,例如不仅仅是随机垃圾),因此没有“随机”填充。另一个冒险是,当我比较相同场景的两个保存文件时,它们看起来是一样的。
编辑 2 我想得越多,我就越意识到我需要跨平台的解决方案。我们主要在 msvc2013 上开发,但我们的应用程序最终构建在 msvc2012 和 clang 上。但是如果我在 msvc2013 中检测到并去掉所有编译器生成的填充,则不能保证其他编译器不会插入填充...(所以 msvc2013 检测是不够的)
【问题讨论】:
-
你认为你为什么需要这个?
-
Padding 的行为很像一个未命名的成员。由于无法枚举成员,因此无法区分普通成员和充当填充的“未命名成员”。
-
您知道可以使用代码生成配置页面中的“结构成员对齐”选项指定 MSVC 填充行为,对吧?
-
@JeroenBaert:这只是他试图检测的变异来源之一。如示例代码所示,也可以逐类定义。
-
在很多情况下你可以使用
std::has_unique_object_representations。见Compile-time check to make sure that there is no padding anywhere in a struct
标签: c++ visual-c++ padding typetraits