Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Using .tupleof

The .tupleof struct property can be used to deal with structs generically.

Basic usage

struct S { int a,b; }
S s;
s.tupleof[1] = 42;

Iterating

The index to .tupleof must be const, so you cannot, for instance, do:

struct S { ... }
S s;
for (size_t i = 0; i < s.tupleof.length; ++i)
    Stdout (s.tupleof[i]).newline;	// error: i is not const

But it is possible to use foreach:

void printStruct(T) (T s)
{
    static assert (is(T == struct), "Only to be used with structs.");
    
    foreach (x,y; s.tupleof)
        Stdout.format ("Element: {}:{}", x,y).newline;
}
It doesn't seem to be possible to set the elements of a struct using foreach, however (correct me if I'm wrong; I couldn't make it work).

Setting the elements

The following is a function I wrote to set all elements of a struct from a static array, to get around the difficulty of setting elements while iterating over the tuple. (It could easily be converted to read from a dynamic array.)

// only used for error reporting:
// Int-to-string converter, which may not be efficient but will run at compile time.
static char[] int2str (uint i) {
    char[] ret;
    const digits = "0123456789";
    if (i == 0) ret = "0";
    else for (; i > 0; i /= 10) ret = digits[i%10] ~ ret;
    return ret;
}

/** Set a struct's elements from an array, where all elements in the struct have the same type (or
 * can be implicitly converted to from the same type).
 *
 * ---
 * struct S { int a,b,c; }
 * S s;
 * int[3] v = [1,2,3];
 * setStruct (s,v);
 * ---
 *
 * It works fine. I'm not sure about the efficiency (do the recursive calls get inlined?).
 */
void setStruct(S, T, size_t N, size_t i = 0) (ref S s, T[N] src) {
    static assert (is(S == struct), "Only to be used with structs.");
    static assert (N == S.tupleof.length, "src.length == "~int2str(N)~"; should equal "~int2str(S.tupleof.length));
    static if (i < N) {
        s.tupleof[i] = src[i];
        setStruct!(S, T, N, i+1) (s, src);
    }
}

Example

Using the above functions, this can be done:

struct S2
{
    //char[] first, second, third;
    uint a;
    byte b;
    ulong c;
    float d;
}

void main() {
    S2 v;
    //char[][3] vals = ["One"[], "Two", "Three"];
    long[4] vals = [-1L,-100,10000000000, 2];
    setStruct(v, vals);
    printStruct(v);
}

Source

Posted by Cyborg16
Date August 4, 2008