Is it possible to write a single templated function to increment the (numeric) fields of different structs? For example:
struct Color
{
ubyte a,r,g,b;
}
struct Point
{
double x, y;
}
I tried something like this:
T update(T, A)(T t, A a)
if (is(T == struct))
{
auto vals = t.tupleof;
foreach (i; 0 .. vals.length) {
vals[i] += a; // error: i cannot be read at compile time
}
return T(vals); // convert back to struct
}
I have also tried writing function templates that accept tuples, but the tuples are always expanded, which prevents the compiler from matching the correct template. Thanks.
Well, I'd say that what you're trying doing is rather bizarre, but it's certainly possible. The most naive, in-place way would probably be:
void update(T)(ref T t)
if(is(T == struct))
{
foreach(ref var; t.tupleof)
++var;
}
The simplest way to do it with a copy would probably be to copy it and then update it rather than trying to construct a new one with updated values (though I'm sure that that can be done too if you really want to):
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
The main problem here, of course, is that the template constraint on both of these is far too weak. All you have to do is have unincrementable types in your struct, and it won't work. The simplest way to fix that would probably be to create an eponymous template to test it for you:
T update(T)(T t)
if(isIncrementableStruct!T)
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
template isIncrementableStruct(T)
{
enum isIncrementableStruct = is(T == struct) &&
is(typeof({T t; foreach(var; t.tupleof) ++var;}));
}
And if you want to be able to increment all of the fields that are incrementable and leave the others alone, you'd probably do something like:
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
{
static if(canIncrement!(typeof(var)))
++var;
}
return copy;
}
template canIncrement(T)
{
enum canIncrement = is(typeof({T var; ++var;}));
}
In any case, the main thing that you appear to have missed was to attempt iterating over tupleof
directly while using ref
so that the elements were updated rather than having copies of them being updated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With