pfr icon indicating copy to clipboard operation
pfr copied to clipboard

add support for bit-fields

Open bgaifullin opened this issue 4 years ago • 3 comments
trafficstars

Lets implement support for bit-fields for read-only mode.

bgaifullin avatar May 18 '21 16:05 bgaifullin

C++14 loophole and classic methods don't work constexpr time. So I'm focusing on the C++17 solution.


I created a branch, and some changes.

First, I modified the structure binding functions to return not the tuples of references, but getter and setter lambdas. Getter has the option to get by reference or by value. So now the types can be returned without trying to get member references.

I tried to manage the has_bitfield_member<T> decision problem from 2 sides.

Has/Is bitfield member

a can_has_a_bitfield check which returns true, if the class can contain a bitfield. This is too wide currently, if a struct has any integral type, the function returns true. (note: bitfield can only be integral type)


a clearly_has_a_bitfield check which returns true, if the class knowly contains a bitfield. This is not handling all the cases.

Missing parts:

  • packed structures (but can be static_assert)
  • if size equals to sequence_tuple::tuple<types...> (aka the bitfields use the same size as if they weren't bitfields) :
    • not trivial types. (This probably can be tightened for the types that contain any member that is not constexpr default initializable)
    • contains a bool member.
    • contains a bitfield with maximum wide, like char c: 8;

Bitfield offset and size

A bitfield size can be calculated with this trick (except for bool-s)

For the bitfield offset I can not come up with an idea with standard C++17, constexpr time.


C++20 has more opportunity to "guess" the type layout with the layout compatible type trait, and the bit cast. These help for the bitfield offset, but not all the cases; only for the standard_layout types.

schaumb avatar Mar 09 '22 18:03 schaumb

Probably can be managed to create not only "read-only" mode, but "proxy" mode too. So If integral types return with a proxy type like:

template<class Getter, class Setter>
struct Proxy {
    using type = std::invoke_result_t<Getter, /*no reference*/>;
    operator type() const {
      return getter(/* no reference */);
    }
    operator type&() const {
      return getter(/*reference*/);
    }
    template<class Any>
    Proxy& operator=(Any&& val) {
        setter(val);
        return *this;
    }
private:
    Getter getter;
    Setter setter;
};

This can be used for bitfield structs too.

schaumb avatar Mar 09 '22 18:03 schaumb

C++20 is helping. With consteval and layout_compatible it can be guessed the bit-field members and their sizes.

So the clearly_has_a_bitfield check cases can be solved.

Remaining limitation:

  • if size equals to sequence_tuple::tuple<types...> (aka the bitfields use the same size as if they weren't bitfields) AND it contains integral type AND
    • any member is non-copiable, non-movable and non-default-constructible
    • if the class is not standard layout type OR the compiler does not support __cpp_lib_is_layout_compatible (clang), and:
      • contains a bool member
      • contains a bitfield with maximum wide, like char c: 8;

schaumb avatar Jan 09 '24 18:01 schaumb