好吧,我想说你正在尝试做的事情很奇怪,但这当然是可能的。最天真、就地的方式可能是:
void update(T)(ref T t)
if(is(T == struct))
{
foreach(ref var; t.tupleof)
++var;
}
使用副本执行此操作的最简单方法可能是复制它然后更新它,而不是尝试使用更新的值构造一个新的(尽管我确信如果你真的想要也可以这样做):
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
当然,这里的主要问题是对这两者的模板约束太弱了。你所要做的就是在你的结构中有不可增加的类型,它不会工作。解决这个问题的最简单方法可能是创建一个同名模板来为您测试它:
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;}));
}
如果您希望能够增加所有可增加的字段而让其他字段保持不变,您可能会执行以下操作:
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;}));
}
无论如何,您似乎错过的主要事情是tupleof
在使用时尝试直接迭代,ref
以便更新元素而不是更新它们的副本。