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