interest in a flag library

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

interest in a flag library

Boost - Dev mailing list
Hi all,

This is the first time I post on this mailing list :).
I'm posting because i'd like to know if people would be interested in a
library to treat enum types as flags. I find that's something which is
lacking in the language since the introduction of strongly typed enums, and
I've since written some code in order to do this.
So far I've seen some discussion on this mailing list about that, but it
doesn't seems that any library have been written yet.
So do you think it is worth the effort of porting and documenting my code
so that it can integrated into boost, or not?

Regards,
Masse Nicolas.

PS:
For those interested, the code consists of a flag class, and overloads
operators like '|' or &.
It can be used like this:

enum struct option : uint
{
    none = 0,
    first = 1,
    second = 2,
    third = 4,
    forth = 8
};

static constexpr flags<option> var1 = option::first;
static constexpr flags<option> var2 = option::second | option::third;
static constexpr auto var3 = var1 | var2; /* type will be resolved into
flags<option> */
static constexpr auto var4 = option::first | option::second |
option::third; /* works too */

int main()
{
    std::cout << var1 << std::endl;
    std::cout << static_cast<uint>(var2) << std::endl; /* note that
static_cast<int> won't compile since the underlying type is uint */
    std::cout << (var3 & option::forth) << std::endl;
    std::cout << (var3 == var4) << std::endl;

    return 0;
}

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list
> So do you think it is worth the effort of porting and documenting my code
> so that it can integrated into boost, or not?

It's for sure something I have encountered.

> static constexpr auto var4 = option::first | option::second |
> option::third; /* works too */

How do you get this one to work?

F

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
czw., 25 paź 2018 o 23:28 Masse Nicolas via Boost <[hidden email]>
napisał(a):

> Hi all,
>
> This is the first time I post on this mailing list :).
> I'm posting because i'd like to know if people would be interested in a
> library to treat enum types as flags. I find that's something which is
> lacking in the language since the introduction of strongly typed enums, and
> I've since written some code in order to do this.
> So far I've seen some discussion on this mailing list about that, but it
> doesn't seems that any library have been written yet.
> So do you think it is worth the effort of porting and documenting my code
> so that it can integrated into boost, or not?
>

Hi. I would use a type-safe library for flags. I am missing one today.
However, given that you provide your own type (which is good IMO), I would
expect a different interface that reflects the meaning more directly. I
consider bit-wise operations to be a hack rather than a proper solution.
Expression `flags & Flags::EXEC` is quite idiomatic, but when I want to
reset a flag, I have to write `flag &=~ Flag::EXEC` (which I call an 'oil
lamp' operator), which is difficult to understand and likely to get wrong.
(In fact, I am not sure I got it right in this example.)

I would rather expect an interface using named functions or indexing
operator:

```
if (!flags[Flag::READ])
  flags.reset(Flag::EXEC);
```

Regards,
&rzej;

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list

> On 26. Oct 2018, at 09:35, Andrzej Krzemienski via Boost <[hidden email]> wrote:
>
> Hi. I would use a type-safe library for flags. I am missing one today.
[…]
> I would rather expect an interface using named functions or indexing
> operator:
>
> ```
> if (!flags[Flag::READ])
>  flags.reset(Flag::EXEC);
> ```

There are std::bitset (fixed size, allocates on the stack) and boost::dynamic_bitset (dynamic size, allocates from stack and heap)

https://www.boost.org/doc/libs/1_68_0/libs/dynamic_bitset/dynamic_bitset.html

The latter also has more sensible implementations of operator& and operator|. Before you invent a new thing, what is wrong with these classes?

Best regards,
Hans

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list

> There are std::bitset (fixed size, allocates on the stack) and boost::dynamic_bitset (dynamic size, allocates from stack and heap)
>
> https://www.boost.org/doc/libs/1_68_0/libs/dynamic_bitset/dynamic_bitset.html
>
> The latter also has more sensible implementations of operator& and operator|. Before you invent a new thing, what is wrong with these classes?

Naming and type safety.

Example: `File open(std::path, AccessMode)`
Usage: `auto file = open("myPath/filename.foo", AccessMode::Read |
AccessMode::Write)`

- Named access to bits (Read/Write) instead of indices
- Type safety: AccessMode instead of std::bitset, and you can't pass
e.g. Includes::All to AccessMode just the same as strong enums protect
against a similar issue




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

smime.p7s (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Right now my code provide the "+" and the "-" operators to set or reset
flags. Anyway, I see no problem in adding some named function for those who
prefer using them.

Masse Nicolas.

Le ven. 26 oct. 2018 à 09:35, Andrzej Krzemienski via Boost <
[hidden email]> a écrit :

> czw., 25 paź 2018 o 23:28 Masse Nicolas via Boost <[hidden email]>
> napisał(a):
>
> > Hi all,
> >
> > This is the first time I post on this mailing list :).
> > I'm posting because i'd like to know if people would be interested in a
> > library to treat enum types as flags. I find that's something which is
> > lacking in the language since the introduction of strongly typed enums,
> and
> > I've since written some code in order to do this.
> > So far I've seen some discussion on this mailing list about that, but it
> > doesn't seems that any library have been written yet.
> > So do you think it is worth the effort of porting and documenting my code
> > so that it can integrated into boost, or not?
> >
>
> Hi. I would use a type-safe library for flags. I am missing one today.
> However, given that you provide your own type (which is good IMO), I would
> expect a different interface that reflects the meaning more directly. I
> consider bit-wise operations to be a hack rather than a proper solution.
> Expression `flags & Flags::EXEC` is quite idiomatic, but when I want to
> reset a flag, I have to write `flag &=~ Flag::EXEC` (which I call an 'oil
> lamp' operator), which is difficult to understand and likely to get wrong.
> (In fact, I am not sure I got it right in this example.)
>
> I would rather expect an interface using named functions or indexing
> operator:
>
> ```
> if (!flags[Flag::READ])
>   flags.reset(Flag::EXEC);
> ```
>
> Regards,
> &rzej;
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On Thu, Oct 25, 2018 at 11:28 PM Masse Nicolas via Boost <
[hidden email]> wrote:

> Hi all,
>
> [...]
>
> enum struct option : uint
> {
>     none = 0,
>     first = 1,
>     second = 2,
>     third = 4,
>     forth = 8
> };
>
> static constexpr flags<option> var1 = option::first;
> static constexpr flags<option> var2 = option::second | option::third;
> static constexpr auto var3 = var1 | var2; /* type will be resolved into
> flags<option> */
> static constexpr auto var4 = option::first | option::second |
> option::third; /* works too */
>

I think a better approach is to fully define the flag type as a class
(without the enum). It gives you slightly less typing for the user. Such
flags type would be defined similar to how the NamedType library is used.
There's also a neat trick to not have to manually specify powers of two
(and possibly get it wrong) using a separate type for bit numbers.

using my_flags_type = flag_type<std::uint8, struct my_flags_tag>;
constexpr my_flags_type red = 0_bit;
constexpr my_flags_type green = 1_bit;
constexpr my_flags_type blue = 2_bit;

I describe such a flag type in this lightning talk:
https://www.youtube.com/watch?v=NGrnKr9rSz4

--
Arvid Norberg

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list
On Sun, Oct 28, 2018 at 7:01 PM Arvid Norberg via Boost <
[hidden email]> wrote:

> On Thu, Oct 25, 2018 at 11:28 PM Masse Nicolas via Boost <
> [hidden email]> wrote:
>
> > Hi all,
> >
> > [...]
> >
> > enum struct option : uint
> > {
> >     none = 0,
> >     first = 1,
> >     second = 2,
> >     third = 4,
> >     forth = 8
> > };
> >
> > static constexpr flags<option> var1 = option::first;
> > static constexpr flags<option> var2 = option::second | option::third;
> > static constexpr auto var3 = var1 | var2; /* type will be resolved into
> > flags<option> */
> > static constexpr auto var4 = option::first | option::second |
> > option::third; /* works too */
> >
>
> I think a better approach is to fully define the flag type as a class
> (without the enum).
>

I think it valuable to have the enum approach for a relatively simple
handling of third-party libraries, etc. that know nothing of this library,
as it would involve little to no effort to use them within this library.
Perhaps one might explore both approaches?

This enum approach eases adoption by allowing someone to use this class
with existing enumerations, such as std::ios::flags.  Although, I am
concerned that it may lack the handling of enums not cast as a class or
struct.  How would it identify the appropriate type to which to resolve in
such situations?

- Trey

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Le 26/10/2018 à 10:08, Hans Dembinski via Boost a écrit :

>> On 26. Oct 2018, at 09:35, Andrzej Krzemienski via Boost <[hidden email]> wrote:
>>
>> Hi. I would use a type-safe library for flags. I am missing one today.
> […]
>> I would rather expect an interface using named functions or indexing
>> operator:
>>
>> ```
>> if (!flags[Flag::READ])
>>   flags.reset(Flag::EXEC);
>> ```
> There are std::bitset (fixed size, allocates on the stack) and boost::dynamic_bitset (dynamic size, allocates from stack and heap)
>
> https://www.boost.org/doc/libs/1_68_0/libs/dynamic_bitset/dynamic_bitset.html
>
> The latter also has more sensible implementations of operator& and operator|. Before you invent a new thing, what is wrong with these classes?
>
Their size. The size of std::bitset<8> is not 8 bits but very often 64
bits. :(

We need something like std::bitset<N>, where we can define the size of
the block xxx::bitset<20, unsigned char>.

The size of xxx::bitset<20, unsigned char> should be 3 bytes.

Aside this point relative to the size, there is also the fact that
std::bitset<N> uses only index between 0 and N-1.

I've defined a ordinal library where the index is not a number between 0
and N-1, but any type that is isomorphic to O..N-1.

https://github.com/viboes/std-make/tree/master/include/experimental/fundamental/v3/ordinal

This library defines several container and in particular an ordinal_set
https://github.com/viboes/std-make/blob/master/include/experimental/fundamental/v3/ordinal/containers/ordinal_set.hpp



but also an ordinal array
https://github.com/viboes/std-make/blob/master/include/experimental/fundamental/v3/ordinal/containers/ordinal_array.hpp

and an ordinal range


You can find a draft proposal here
https://github.com/viboes/std-make/blob/master/doc/proposal/ordinal/Ordinal.md

In particular enums with power of 2 constants are isomorphic to 0..N-1.



Unfortunately ordinal_set<O> when the cardinality of O is 24 is not 3
bytes as I use std::bitset as underlying implementation.


I started an implementation of a bitmask that has a builtin unsigned int
underlying representation in

https://github.com/viboes/std-make/blob/master/include/experimental/fundamental/v3/bits/bit_mask.hpp

but I have not put both together.

Please, be free to take whatever could be useful to you.

Hopping this helps,
Vicente




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: interest in a flag library

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Le lun. 29 oct. 2018 à 00:01, Arvid Norberg <[hidden email]> a
écrit :

> On Thu, Oct 25, 2018 at 11:28 PM Masse Nicolas via Boost <
> [hidden email]> wrote:
>
>> Hi all,
>>
>> [...]
>>
>> enum struct option : uint
>> {
>>     none = 0,
>>     first = 1,
>>     second = 2,
>>     third = 4,
>>     forth = 8
>> };
>>
>> static constexpr flags<option> var1 = option::first;
>> static constexpr flags<option> var2 = option::second | option::third;
>> static constexpr auto var3 = var1 | var2; /* type will be resolved into
>> flags<option> */
>> static constexpr auto var4 = option::first | option::second |
>> option::third; /* works too */
>>
>
> I think a better approach is to fully define the flag type as a class
> (without the enum). It gives you slightly less typing for the user. Such
> flags type would be defined similar to how the NamedType library is used.
> There's also a neat trick to not have to manually specify powers of two
> (and possibly get it wrong) using a separate type for bit numbers.
>
> using my_flags_type = flag_type<std::uint8, struct my_flags_tag>;
> constexpr my_flags_type red = 0_bit;
> constexpr my_flags_type green = 1_bit;
> constexpr my_flags_type blue = 2_bit;
>
> I describe such a flag type in this lightning talk:
> https://www.youtube.com/watch?v=NGrnKr9rSz4
>
> --
> Arvid Norberg
>

Hi,

I had a quick look at your presentation. While I do think that using a
class is an option, I still prefer to use enums for that, for several
reasons:
- The use of an enum for the values makes a clear differences betwen them
and the flags (which are a combinaison of those values).
- The use of enums allows to scope the values inside their name, while
using your solution makes them visible directly inside your namespace.
- The need of a tag struct is be a bit odd, espescially for now comers
Anyway, I should say I like the idea of having an helper class to avoid the
specification of to power of two. As a consequence, I will probably add
something similar in my code.

Nicolas.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost