Vâng, tôi muốn nói rằng những gì bạn đang cố gắng làm là khá kỳ lạ, nhưng chắc chắn là có thể. Các ngây thơ nhất, tại chỗ cách có lẽ sẽ là:
void update(T)(ref T t)
if(is(T == struct))
{
foreach(ref var; t.tupleof)
++var;
}
Cách đơn giản nhất để làm điều đó với một bản sao có lẽ sẽ để sao chép nó và sau đó cập nhật nó chứ không phải là cố gắng để xây dựng một cái mới với các giá trị được cập nhật (mặc dù tôi chắc chắn rằng điều đó cũng có thể được thực hiện nếu bạn thực sự muốn):
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
Vấn đề chính ở đây, là ràng buộc mẫu trên cả hai yếu tố này quá yếu. Tất cả những gì bạn phải làm là có các loại không thể tách rời trong cấu trúc của bạn và nó sẽ không hoạt động. Cách đơn giản nhất để khắc phục điều đó có lẽ sẽ là để tạo ra một mẫu cùng tên để kiểm tra điều đó cho bạn:
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;}));
}
Và nếu bạn muốn để có thể tăng tất cả các lĩnh vực có incrementable và để lại những người khác một mình, bạn 'd lẽ làm một cái gì đó như:
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;}));
}
trong mọi trường hợp, điều chính mà bạn dường như đã bỏ qua là để cố gắng iterating qua tupleof
trực tiếp trong khi sử dụng ref
để các yếu tố đã được cập nhật thay vì phải bản sao của chúng là đã cập nhật.
Nguồn
2012-06-09 06:36:24
thuật sĩ tuyệt vời! – YGL