Bene, direi che quello che stai cercando di fare è piuttosto bizzarro, ma è certamente possibile. Il, in-place modo più ingenuo sarebbe probabilmente:
void update(T)(ref T t)
if(is(T == struct))
{
foreach(ref var; t.tupleof)
++var;
}
Il modo più semplice per farlo con una copia probabilmente sarebbe copiarlo e poi aggiornarlo piuttosto che cercare di costruire una nuova con valori aggiornati (anche se sono sicuro che questo può essere fatto anche se si vuole veramente):
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
il problema principale, naturalmente, è che il vincolo modello su entrambi questi è troppo debole. Tutto quello che devi fare è avere tipi non ricorrenti nella tua struct, e non funzionerà. Il modo più semplice per risolvere il problema che probabilmente sarebbe di creare un modello omonimo per testarlo per voi:
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;}));
}
E se si vuole essere in grado di incrementare tutti i campi che sono incrementabile e lasciare in pace gli altri, 'd probabilmente fare qualcosa di simile:
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 ogni caso, la cosa principale che si sembrano aver perso è stato quello di tentare l'iterazione su tupleof
direttamente durante l'utilizzo ref
in modo che gli elementi sono stati aggiornati, piuttosto che avere copie di loro che sono aggiornato.
fonte
2012-06-09 06:36:24
incredibile magia! – YGL