samedi 4 novembre 2017

Portable Bitfield : Is this Legal

I was trying to make a bitfield substitute. The primary motive is to have something that can be easily serialized / deserialized. So I created a bitfield class.

template <typename T, size_t ...SIZES>
struct BitField {

   using Type = T;

   template <size_t I>
    void set (T v)
    {
        ...
    }

    template <size_t I>
    T get ()
    {
       ...
    }

    T value_;
};

So a bitfiled can be created like below:

BitField<uint16_t, 4, 3, 9> field; // creates a 4bit, 3bit and 9bit field in a uint16_t

But there is no nice way to set and get the field. With the above interface, we get and set each field by index.

field.get<0>()
field.set<0>(10)

I wanted to give it a easy syntax, like a variable access and assignment. And I am not clear how I can do it. I created a Field class. The idea is to make a union :

struct Mpls {

    using BF = BitField<uint32_t, 20, 3, 1, 8>;

    union  Label {

        BF _bf;

        Field<0, BF> _label; // this will act like a variable
        Field<1, BF> _exp;
        Field<2, BF> _eos;
        Field<3, BF> _ttl;

    } label;
};

The Field class is defined as below. But I don't know if this is strictly legal?

template <size_t I, typename BF>
struct Field {

    using Type = typename BF::Type;

    void operator = (Type v)
    {
        // typecast 'this' to 'BitField class' and here is where I have doubt if this is okay.
        ((BF *)this)->template set<I>(v);
    }

    operator Type()
    {
        return ((BF *)this)->template get<I>();
    }
};

I can set the fields like this.

mpls.label._ttl = 0xff;

This works. But is it okay to do this?

Aucun commentaire:

Enregistrer un commentaire