iterating through members of bitfields
Ali Çehreli via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Jan 20 14:12:58 PST 2017
On 01/19/2017 05:21 PM, Nestor wrote:
> On Wednesday, 18 January 2017 at 12:52:56 UTC, drug wrote:
>> I've "solved" the same problem by using AliasSeq to generate bitfields
>> so that for iterating over bitfields I can iterate over alias sequence
>> and mixin code. Not very good but it works.
>
> Interesting, could you provide a working example?
Here is 'iterableBitfields' that mixes in both a static array of bit
field specs and a range that iterates through their values. Obviously,
because the range must have one element type, you have to specify what
works you: int, string, etc.
import std.stdio;
import std.bitmanip;
import std.string;
import std.typecons;
import std.conv;
import std.algorithm;
string makeBitfieldSpecs(IterValueType, Args...)(string specsPrefix) {
static assert(Args.length % 3 == 0);
string members;
string type;
string name;
size_t width;
string value;
foreach (i, arg; Args) {
static if (i % 3 == 0) {
type = arg.stringof;
}
else static if (i % 3 == 1) {
name = arg;
}
else {
width = arg;
value = format("(typeof(this) obj) => obj.%s().to!%s",
name, IterValueType.stringof);
members ~= format(`tuple("%s", "%s", %s, %s),`,type, name,
width, value);
}
}
string specsArray = format("static const %sSpecs = [ %s ];",
specsPrefix, members);
string specsFunc = format(q{
auto %sValues() const {
return %sSpecs.map!(spec => spec[3](this));
}}, specsPrefix, specsPrefix);
return specsArray ~ specsFunc;
}
string iterableBitfields(string specsPrefix, IterValueType, Args...)() {
return bitfields!Args ~ makeBitfieldSpecs!(IterValueType,
Args)(specsPrefix);
}
struct S {
int myVar;
mixin (iterableBitfields!("myFields", // prefix for names of
mixed-in array and func
int, // the type to present field
values in (can be string)
// Regular args to std.typecons.bitfields
follow:
int, "a", 24,
byte, "b", 8));
}
void main() {
auto s = S();
s.myVar = 42;
s.a = 1;
s.b = 2;
/* The struct gains two additional members:
* <prefix>Specs: An array of tuples
* <prefix>Values: A range of field values
*/
writefln("The specs (last one is a lambda):\n%( %s\n%)",
s.myFieldsSpecs);
writefln("The values: %(%s, %)", s.myFieldsValues);
// You must pass the object when calling the value lambda explicitly.
// Here is the value of 'a' through the lambda in the spec:
assert(s.a == s.myFieldsSpecs[0][3](s)); // Note 's' is passed to
lambda
}
Ali
More information about the Digitalmars-d-learn
mailing list