Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if struct has padding

Is there a way (trait or so) to detect, if struct/class has some padding?

I don't need cross-platform or standardized solution, I need it for MSVC2013.

I can check it like

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);

But C++ doesn't allow (as far as I know) generate this non-invasive (without touching existing structs)

Ideally I would like to get working something like this

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{};

EDIT - Why do I need this?

I'am working with existing serialization system, which store some struct just taking void* to them (inside generic function) and store sizeof(T) number of bytes... Such binary file is not portable on platforms we are targeting, since different compilers are used, so there is no guarantee how is padding inserted. If I could statically detect all T which are structs with padding, I can force user to manually insert padding (some control padding e.g. not just random garbage) so there is no "random" padding. Another adventage is, when I diff two save files of same scenerio, they will look the same.

edit 2 the more I think about it, the more I realize I need cross-platform solution. We mainly develop on msvc2013 but our application is at final builded in msvc2012 and clang. But if I detected and get rid of all compiler-generated padding in msvc2013, there is no guarantee that other compiler doesn't insert padding... (so msvc2013 detection is not enough)

like image 339
relaxxx Avatar asked Aug 14 '15 09:08

relaxxx


1 Answers

Do you need this information during run time? Because if you want to know it in build time I believe you can use static_assert to get this information.

struct foo
{
    uint64_t x;
    uint8_t y;
};
#define EXPECTED_FOO_SIZE (sizeof(uint64_t) + sizeof(uint8_t))
static_assert(sizeof(foo) == EXPECTED_FOO_SIZE, "Using padding!");

If you need it during run time, you can try something like:

static const bool has_padding = (sizeof(foo) != EXPECTED_FOO_SIZE);

Also check this link from earlier post, maybe it will help.

like image 194
Alex Lop. Avatar answered Nov 06 '22 12:11

Alex Lop.