是否有方法(trait或其他)检测struct/class是否有填充?
我不需要跨平台或标准化的解决方案,我需要它用于MSVC 2013。
我可以检查一下
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
结构体,它们是带有填充的,我可以强制用户手动插入填充(一些控制填充,例如,不仅仅是随机垃圾),这样就没有“随机”填充。另一个优点是,当我比较两个相同场景的保存文件时,它们看起来是一样的。
edit 2我越想越觉得我需要跨平台的解决方案。我们主要是在msvc 2013上开发的,但是我们的应用程序最后是在msvc 2012和clang中构建的。但是如果我在msvc 2013中检测到并清除了所有编译器生成的填充,就不能保证其他编译器不会插入填充...(所以msvc 2013检测是不够的)
4条答案
按热度按时间vptzau2j1#
你在运行时需要这些信息吗?因为如果你想在构建时知道这些信息,我相信你可以使用static_assert来获得这些信息。
如果您在运行时需要它,可以尝试类似以下的操作:
也检查这个link从早期的职位,也许它会有帮助。
3yhwsihp2#
尝试使用此宏:
现在,在运行时您可以测试:
和ofc,如果想在编译时得到错误,可以使用static_assert。
hsvhsicv3#
C++17中最接近的是
std::has_unique_object_representations
,它基本上是您建议的has_padding<T>
结构的布尔逆,但它也不能用于浮点类型。在我的代码库中,我使用了
std::has_unique_object_representations_v<T> || std::is_same_v<T, float> || std::is_same_v<T, double>
的组合来检查我需要什么,但是这不包括float
是成员变量的情况。您可能需要创建自己的
has_padding
实现结构,该结构具有服从std::has_unique_object_representations<T>
的泛型实现,其中包含float
或double
成员的自定义类型可以在您手动检查之后添加专门化:它并不完美,但据我所知,它是最接近于自动检查C++中的结构填充的。
w8rqjzmb4#
也许你应该试试这样的东西:
我得到了:
我使用的是Ubuntu 14.04。