Cóż, powiedziałbym, że to, co próbujesz, jest dość dziwne, ale na pewno jest możliwe. Najbardziej naiwny, sposobem na miejscu będzie prawdopodobnie:
void update(T)(ref T t)
if(is(T == struct))
{
foreach(ref var; t.tupleof)
++var;
}
Najprostszy sposób to zrobić kopię będzie prawdopodobnie go skopiować, a następnie zaktualizować go zamiast próbować skonstruować nowe z zaktualizowanych wartości (choć jestem pewien, że można zrobić zbyt jeśli naprawdę chcesz):
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
głównym problemem tutaj, oczywiście, jest to, że ograniczenie szablon na obu z nich jest zbyt słaby. Wszystko, co musisz zrobić, to mieć niewymienne typy w twojej strukturze i to nie zadziała. Najprostszym sposobem, aby ustalić, że będzie prawdopodobnie do stworzenia tytułowego szablon przetestować go dla Ciebie:
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;}));
}
A jeśli chcesz, aby móc zwiększyć wszystkich pól, które są incrementable i zostawić na innych, byłyby prawdopodobnie zrobić coś takiego:
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;}));
}
W każdym razie najważniejsze, że wydaje się, że brakowało próba Iterowanie nad tupleof
bezpośrednio podczas korzystania ref
tak, że elementy zostały zaktualizowane zamiast ich kopie są zaktualizowany.
Niesamowita magia! – YGL