foonathan / type_safe

Zero overhead utilities for preventing bugs at compile time
https://type_safe.foonathan.net
MIT License
1.54k stars 122 forks source link

Bitwise operations for integer_ops #135

Open stevemk14ebr opened 2 years ago

stevemk14ebr commented 2 years ago

Cool library!

The type_safe::strong_typedef_op could use the bitwise operations like &, |, ~, etc. For the integer op type these should probably be default.

stevemk14ebr commented 2 years ago

Motivating example. On windows typedef DWORD ACCESS_MASK;. To check the flags one must do bitwise checks like mask & GENERIC_READ etc. This type can't be recreated with the strong_types as is.

gerboengels commented 2 years ago

If you define your type like this

struct my_access_mask : type_safe::strong_typedef<my_access_mask, DWORD>,
                type_safe::strong_typedef_op::bitmask<my_access_mask>
{
    using strong_typedef::strong_typedef;
};

my_access_mask add_read(my_access_mask mask) {
  return mask & my_access_mask{ GENERIC_READ };
}

you get what you want, I think. Godbolt link https://godbolt.org/z/6Knj6sjbq

See Jonathan's blog post/tutorial as well, for some background on how to use this very useful library

stevemk14ebr commented 2 years ago

I did not notice the bitmask op existed thank you. Perhaps this could be added to the integer ops by default, I had expected them to be present there.

stevemk14ebr commented 2 years ago

hmm doing mask & MY_ACCESS_MASK{ GENERIC_READ } isn't giving me a bool as I'd like. By default the bitwise mask is giving back another MY_ACCESS_MASK, an automatic bool operator would be nice.

foonathan commented 2 years ago

I did not notice the bitmask op existed thank you. Perhaps this could be added to the integer ops by default, I had expected them to be present there.

I'm trying to make an explicit distinction between "integer operations" and "bit operations". In my opinion, integers and bit strings are different types and should be treated differently.

hmm doing mask & MY_ACCESS_MASK{ GENERIC_READ } isn't giving me a bool as I'd like. By default the bitwise mask is giving back another MY_ACCESS_MASK, an automatic bool operator would be nice.

The library explicitly tries to prevent implicit conversions. If you want, you can always write one:

struct my_access_mask : type_safe::strong_typedef<my_access_mask, DWORD>,
                type_safe::strong_typedef_op::bitmask<my_access_mask>
{
    using strong_typedef::strong_typedef;

     operator bool() const
    { return static_cast<DWORD>(*this) != 0; }
};

my_access_mask add_read(my_access_mask mask) {
  return mask & my_access_mask{ GENERIC_READ };
}

You might also be interested in using type_safe::flag_set instead: https://www.foonathan.net/2017/03/implementation-challenge-bitmask/