digitalmars.D.learn - Bitfield-style enum to strings?
- Nick Sabalausky (17/17) May 07 2015 Assuming a plain old bitfield-style enum like:
- Baz (6/23) May 07 2015 Hi, i have a specialized struct for "bit sets" that handles the
- Nick Sabalausky (39/56) May 07 2015 Wow, D's seriously awesome, that was actually way easier than I expected...
- Nick Sabalausky (39/39) May 07 2015 Minor fix to work right for "none" fields. Already worked fine on
- Nick Sabalausky (5/44) May 07 2015 import std.algorithm : filter, map;
- Justin Whear (2/8) May 07 2015 T[] members = [ EnumMembers!T ];
- Nick Sabalausky (4/12) May 07 2015 Doh! Yup, that works.
- Meta (2/19) May 07 2015 You could also do `TypeTuple!(EnumMembers!T))` I believe.
- Nick Sabalausky (2/13) May 07 2015 filter doesn't seem to like that.
- Meta (2/17) May 08 2015 Yeah, sorry, forgot it was supposed to go through a range as well.
- anonymous (4/10) May 07 2015 only(EnumMembers!T) should work and did work before 2.067. I
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
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
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
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
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
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
On 05/07/2015 05:19 PM, Justin Whear wrote:On Thu, 07 May 2015 16:55:42 -0400, Nick Sabalausky wrote: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.// 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
On Thursday, 7 May 2015 at 21:41:06 UTC, Nick Sabalausky wrote:On 05/07/2015 05:19 PM, Justin Whear wrote:You could also do `TypeTuple!(EnumMembers!T))` I believe.On Thu, 07 May 2015 16:55:42 -0400, Nick Sabalausky wrote: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.// 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
On 05/07/2015 09:17 PM, Meta wrote:On Thursday, 7 May 2015 at 21:41:06 UTC, Nick Sabalausky wrote:filter doesn't seem to like that.On 05/07/2015 05:19 PM, Justin Whear wrote:You could also do `TypeTuple!(EnumMembers!T))` I believe.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
On Friday, 8 May 2015 at 04:11:36 UTC, Nick Sabalausky wrote:On 05/07/2015 09:17 PM, Meta wrote:Yeah, sorry, forgot it was supposed to go through a range as well.On Thursday, 7 May 2015 at 21:41:06 UTC, Nick Sabalausky wrote:filter doesn't seem to like that.On 05/07/2015 05:19 PM, Justin Whear wrote:You could also do `TypeTuple!(EnumMembers!T))` I believe.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 08 2015
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 07 2015









"Baz" <bb.temp gmx.com> 