Boost logo

Boost :

Subject: Re: [boost] Improved typesafe bitfield
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2016-02-06 06:00:22


Le 04/02/2016 16:19, Niall Douglas a écrit :
> Firstly I'd like to thank Vicente and Tongari for their ideas as
> without their feedback I wouldn't have come up with
> https://gist.github.com/ned14/614d8f3cca25924964ea which combines
> ideas from all three of us.
>
> I'm relatively happy with this solution. Declaration is as follows:
>
> BOOST_AFIO_BITFIELD_BEGIN(flag)
> {
> none=0,
> delete_on_close=1,
> disable_safety_fsyncs=2
> }
> BOOST_AFIO_BITFIELD_END(flag)
>
> Example usage:
>
> flag f(flag::disable_safety_fsyncs);
> flag f2(f&flag::none);
> f2|=flag::delete_on_close;
> constexpr flag f3(flag::disable_safety_fsyncs);
> constexpr flag f4(f3&flag::none);
> if(f) ...
Yes, this is much better.
> This solution is convenient for programmers to use, works as you'd
> expect from a bitfield, if(bf) works and is 100% constexpr and
> generates zero runtime overhead, and it's ODR-used correct. The
> tradeoff is unfortunately now individual flag::XXX are not typesafe
> and have implicit convertibility to int, though 'flag' itself and any
> output of any operation on 'flag' is typesafe. Also, there is an ugly
> macro begin and end of the declaration, but I think this is the best
> typesafe bitfield I can think of which has a syntax resembling C
> bitfields.
>
> Any comments absolutely welcome.
>
>
C/C++ bit fields means already something else
(http://en.cppreference.com/w/cpp/language/bit_field).

I will name the utility in some other way.

Do you see something wrong having two classes one for the bits enum and
one for the set of those bits enums?
Mixing both, the element and the set in a single class, has some
drawbacks. The flag type is not an enum, that is, is_enum<flag>::value
is false.

I don't see the added value of the macros and the inheritance

#define BOOST_AFIO_BITFIELD_BEGIN(type) \
struct type##_base \
{ \
   enum enum_type

#define BOOST_AFIO_BITFIELD_END(type) \
;}; \
using type = bitfield<type##_base>;

template<class Enum> struct bitfield : public Enum

Why do you need to inherit from Enum? to introduce the enumerators
inside the defined type?

What about

template<class Enum> struct bitfield_set
{
   using enum_type = Enum;
   using underlying_type = std::underlying_type_t<enum_type>;
private:
   underlying_type _value;

...

enum class flag = unsigned {
   none=0,
   delete_on_close=1,
   disable_safety_fsyncs=2
};

using flags = bitfield_set<flag>;

Example usage:

   flags f(flag::disable_safety_fsyncs);
   flags f2(f&flag::none);
   f2|=flag::delete_on_close;
   constexpr flags f3(flag::disable_safety_fsyncs);
   constexpr flags f4(f3&flag::none);
   if(f) ...

Best,
Vicente

P.S. an bits enum is an enum that is isomorphic to 0, 1, 2, 4, 8 ... 2^n.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk