KonanM / tser

tser - tiny serialization for C++
Boost Software License 1.0
134 stars 7 forks source link

Bitfield support #9

Open DakshKK opened 1 year ago

DakshKK commented 1 year ago

Any way to achieve bitfield support for structs?

KonanM commented 1 year ago

The problem with bitfields is that you can't take a non const reference to or create a non const pointer to it. I experimented a bit and even const references to the last bitfield could behave strangely (maybe it was padding).

So the only "clean" solution seems to be using something like this: https://codereview.stackexchange.com/questions/54342/template-for-endianness-free-code-data-always-packed-as-big-endian which will relies on UB (non active union member access), but it seems to work on a first glance:

struct CustomBitfields2 {
    CustomBitfields2()
    {
        a = 4;
        b = 15;
    }
    DEFINE_SERIALIZABLE(CustomBitfields2, a, b)
    union {
        unsigned char storage = 0;
        BitFieldMember<0, 3> a;
        BitFieldMember<3, 5> b;
    };
};

I would recommend to simply write out the classes that need bitfield support like this:

struct CustomBitfields {
    unsigned int a : 3 = 4;
    unsigned int b : 5 = 15;

    void save(tser::BinaryArchive& ba) const {
        ba.save(a);
        ba.save(b);
    }

    void load(tser::BinaryArchive& ba) {
        unsigned int al = ba.load<unsigned int>();
        a = al;
        unsigned int bl = ba.load<unsigned int>();
        b = bl;
    }

    friend std::ostream& operator<<(std::ostream& os, const CustomBitfields& t) { 
        return os << "{ CustomBitfields : { a: " << t.a << ", b: " << t.b << "} }";
    }
};