jeudi 19 mai 2022

Is there a (portable) way to detect layout change in C++ classes?

For example say I have a class Foo with a typical serialization pattern.

struct Foo {
    int a;
    bool b;
    template <typename Archive>
    void serialize(Archive & ar) {
        ar & a;
        ar & b;
    }
};

Now suppose somebody comes along and adds a field.

struct Foo {
    int a;
    bool b;
    std::string c;

    template <typename Archive>
    void serialize(Archive & ar) {
        ar & a;
        ar & b;
    }
};

This compiles just fine but the Archive method is wrong. I could add something like


namespace detail {
template <int a, int b>
void AssertSizeOfImplementation() {
    static_assert(a == b, "Size does not match (check stack trace)");
}
}  
template <typename T, int size>
void AssertSizeOf() {
    detail::AssertSizeOfImplementation<sizeof(T), size>();
}


struct Foo {
    int a;
    bool b;

    template <typename Archive>
    void serialize(Archive& ar) {
        ar& a;
        ar& b;
        AssertSizeOf<Foo,8>();
    }
};

and now if I add the extra field I will see a compile error

: In instantiation of 'void detail::AssertSizeOfImplementation() [with int a = 40; int b = 8]':

I can then fix my serialization code and update the assertion.

However this is not very portable. sizeof will return different results depending on packing and architecture.

Are there any other alternatives to using sizeof?

( play with this on godbolt https://godbolt.org/z/fMo8ETjnr )





Aucun commentaire:

Enregistrer un commentaire