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


Le 06/02/2016 12:54, Niall Douglas a écrit :
> On 6 Feb 2016 at 12:00, Vicente J. Botet Escriba wrote:
>
>> 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.
> Tongari's solution split them as you describe.
>
> I'm not against that solution, it's just a distinction I need to care
> about during using them and I don't want to care. I just want C
> bitfields which don't accidentally substitute for integers and
> therefore lead to bugs.
I understand you, however I believe that the intent is better reflected
with a type for elements and a a type for the set of elements.
>
>> 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?
> Exactly. I'm effectively wrapping an enum into a typesafe struct with
> member functions.
This makes your bitfield class implementation defined as too dependent.
>
>> 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) ...
> That's absolutely fine if you don't mind distinct types for the
> enumerators and the flags. For me personally, I find myself typing
> the wrong one in my code, and that's a source of compile errors and
> therefore wasted productivity.
Have you tried to name it flag_set instead of flags?
Could you give some examples?
> What is very annoying is that global operator overloads on a class
> enum gets you 98% of the way there. If only one could overload a
> global explicit bool operator ... we'd have our typesafe bit flags
> type.
>
>
This is not the case for scoped enums, or at least not completely as
scoped enums constructor is explicit, isn't it?

Vicente