Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 07, 2015 Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Assuming a plain old bitfield-style enum like: enum Foo { optionA = 1<<0; optionB = 1<<1; optionC = 1<<2; optionD = 1<<3; optionE = 1<<4; } Does a function already exist somewhere to take an instance of Foo and get a list of the switch names as strings? Something kinda like: Foo fooVar = Foo.optionB | Foo.optionD; assert( DOES_THIS_FUNC_EXIST(fooVar) .equals(["optionB", "optionD"]) ); Seems entirely feasible, although my traits-fu is a bit rusty. |
May 07, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Thursday, 7 May 2015 at 17:41:10 UTC, Nick Sabalausky wrote: > Assuming a plain old bitfield-style enum like: > > enum Foo { > optionA = 1<<0; > optionB = 1<<1; > optionC = 1<<2; > optionD = 1<<3; > optionE = 1<<4; > } > > Does a function already exist somewhere to take an instance of Foo and get a list of the switch names as strings? > > Something kinda like: > > Foo fooVar = Foo.optionB | Foo.optionD; > assert( > DOES_THIS_FUNC_EXIST(fooVar) > .equals(["optionB", "optionD"]) > ); > > Seems entirely feasible, although my traits-fu is a bit rusty. Hi, i have a specialized struct for "bit sets" that handles the string representation: https://github.com/BBasile/enumset/blob/master/import/enumset.d#L242 however it's not std. Building the string is easy (cf toString()) but if it can help... |
May 07, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On 05/07/2015 01:41 PM, Nick Sabalausky wrote: > Assuming a plain old bitfield-style enum like: > > enum Foo { > optionA = 1<<0; > optionB = 1<<1; > optionC = 1<<2; > optionD = 1<<3; > optionE = 1<<4; > } > > Does a function already exist somewhere to take an instance of Foo and > get a list of the switch names as strings? > > Something kinda like: > > Foo fooVar = Foo.optionB | Foo.optionD; > assert( > DOES_THIS_FUNC_EXIST(fooVar) > .equals(["optionB", "optionD"]) > ); > > Seems entirely feasible, although my traits-fu is a bit rusty. > Wow, D's seriously awesome, that was actually way easier than I expected: ------------------------------------ import std.traits : isIntegral; auto bitFieldValues(T)(T value) if(is(T==enum) && isIntegral!T) { import std.algorithm : filter, map; import std.conv : to; import std.traits : EnumMembers; // There's gotta be a better way to convert EnumMembers!T // to a range, right? But std.range.only() didn't work, // due to a template instantiation error. T[] members; foreach(m; EnumMembers!(T)) members ~= m; return members .filter!(member => (value & member) == member) .map!(member => to!string(member)); } ------------------------------------ Sample code to use it: ------------------------------------ enum Foo { optionA = 1<<0, optionB = 1<<1, optionC = 1<<2, optionD = 1<<3, optionE = 1<<4, } void main() { import std.range : join; import std.stdio : writeln; Foo fooVar = Foo.optionB | Foo.optionD; // Output: optionB | optionD writeln(bitFieldValues(fooVar).join(" | ")); } ------------------------------------ |
May 07, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | Minor fix to work right for "none" fields. Already worked fine on combination fields liek "all". ------------------------------------- enum Foo { none = 0, optionA = 1<<0, optionB = 1<<1, optionC = 1<<2, optionD = 1<<3, all = optionA | optionB | optionC | optionD, } import std.traits : isIntegral; auto bitFieldValues(T)(T value) if(is(T==enum) && isIntegral!T) { // There's gotta be a better way to convert EnumMembers!T // to a range, right? But std.range.only() didn't work, // due to a template instantiation error. T[] members; foreach(m; EnumMembers!(T)) members ~= m; return members .filter!(member => member==0? value==0 : (value&member)==member) .map!(member => to!string(member)); } void main() { import std.range : join; import std.stdio : writeln; Foo fooVar = Foo.optionB | Foo.optionD; // Output: // optionB | optionD // none // optionA | optionB | optionC | optionD | all writeln(bitFieldValues(Foo.optionB | Foo.optionD).join(" | ")); writeln(bitFieldValues(Foo.none).join(" | ")); writeln(bitFieldValues(Foo.all).join(" | ")); } ------------------------------------- |
May 07, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | Gah, missed some imports that time: On 05/07/2015 05:04 PM, Nick Sabalausky wrote: > Minor fix to work right for "none" fields. Already worked fine on > combination fields liek "all". > > ------------------------------------- > enum Foo > { > none = 0, > optionA = 1<<0, > optionB = 1<<1, > optionC = 1<<2, > optionD = 1<<3, > all = optionA | optionB | optionC | optionD, > } > > import std.traits : isIntegral; > auto bitFieldValues(T)(T value) if(is(T==enum) && isIntegral!T) > { import std.algorithm : filter, map; import std.conv : to; import std.traits : EnumMembers; > // There's gotta be a better way to convert EnumMembers!T > // to a range, right? But std.range.only() didn't work, > // due to a template instantiation error. > T[] members; > foreach(m; EnumMembers!(T)) > members ~= m; > > return members > .filter!(member => member==0? value==0 : (value&member)==member) > .map!(member => to!string(member)); > } > > void main() > { > import std.range : join; > import std.stdio : writeln; > > Foo fooVar = Foo.optionB | Foo.optionD; > > // Output: > // optionB | optionD > // none > // optionA | optionB | optionC | optionD | all > > writeln(bitFieldValues(Foo.optionB | Foo.optionD).join(" | ")); > writeln(bitFieldValues(Foo.none).join(" | ")); > writeln(bitFieldValues(Foo.all).join(" | ")); > } > ------------------------------------- > |
May 07, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Thu, 07 May 2015 16:55:42 -0400, Nick Sabalausky wrote:
> // There's gotta be a better way to convert EnumMembers!T // to a
> range, right? But std.range.only() didn't work, // due to a
> template instantiation error.
> T[] members;
> foreach(m; EnumMembers!(T))
> members ~= m;
T[] members = [ EnumMembers!T ];
|
May 07, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Justin Whear | On 05/07/2015 05:19 PM, Justin Whear wrote:
> On Thu, 07 May 2015 16:55:42 -0400, Nick Sabalausky wrote:
>
>> // There's gotta be a better way to convert EnumMembers!T // to a
>> range, right? But std.range.only() didn't work, // due to a
>> template instantiation error.
>> T[] members;
>> foreach(m; EnumMembers!(T))
>> members ~= m;
>
> T[] members = [ EnumMembers!T ];
>
Doh! Yup, that works.
Still, I would think there should be a way to do it without allocating an array. But it's not a huge deal right now though.
|
May 07, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Thursday, 7 May 2015 at 20:55:42 UTC, Nick Sabalausky wrote: > // There's gotta be a better way to convert EnumMembers!T > // to a range, right? But std.range.only() didn't work, > // due to a template instantiation error. > T[] members; > foreach(m; EnumMembers!(T)) > members ~= m; only(EnumMembers!T) should work and did work before 2.067. I filed a regression: https://issues.dlang.org/show_bug.cgi?id=14556 |
May 08, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Thursday, 7 May 2015 at 21:41:06 UTC, Nick Sabalausky wrote:
> On 05/07/2015 05:19 PM, Justin Whear wrote:
>> On Thu, 07 May 2015 16:55:42 -0400, Nick Sabalausky wrote:
>>
>>> // There's gotta be a better way to convert EnumMembers!T // to a
>>> range, right? But std.range.only() didn't work, // due to a
>>> template instantiation error.
>>> T[] members;
>>> foreach(m; EnumMembers!(T))
>>> members ~= m;
>>
>> T[] members = [ EnumMembers!T ];
>>
>
> Doh! Yup, that works.
>
> Still, I would think there should be a way to do it without allocating an array. But it's not a huge deal right now though.
You could also do `TypeTuple!(EnumMembers!T))` I believe.
|
May 08, 2015 Re: Bitfield-style enum to strings? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On 05/07/2015 09:17 PM, Meta wrote:
> On Thursday, 7 May 2015 at 21:41:06 UTC, Nick Sabalausky wrote:
>> On 05/07/2015 05:19 PM, Justin Whear wrote:
>>>
>>> T[] members = [ EnumMembers!T ];
>>>
>>
>> Doh! Yup, that works.
>>
>> Still, I would think there should be a way to do it without allocating
>> an array. But it's not a huge deal right now though.
>
> You could also do `TypeTuple!(EnumMembers!T))` I believe.
filter doesn't seem to like that.
|
Copyright © 1999-2021 by the D Language Foundation