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

Reply via email to