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
; 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
; 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