April 23, 2009 Re: Struct Flattening | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Max Samukha | On Thu, 23 Apr 2009 10:45:01 +0200, Max Samukha <samukha@voliacable.com.removethis> wrote: > >You could do it like this: > >struct Joint(T...) >{ > T ranges; >} > >template isJoint(T) >{ > enum isJoint = is(typeof(T.ranges)); // or whatever means you >choose to identify a Joint >} > >template JointRetType(T...) >{ > static if (T.length) > { > static if (isJoint!(T[0])) > alias Joint!(typeof(T[0].ranges), >typeof(JointRetType!(T[1..$]).ranges)) JointRetType; > else > alias Joint!(T[0], typeof(JointRetType!(T[1..$]).ranges)) >JointRetType; > } > else > alias Joint!() JointRetType; >} > >private /+ auto +/ Joint!(T) flatJoint(T...)(T args) >{ > return Joint!(T)(args); >} > >/+ auto +/ JointRetType!(T) joint(T...)(T args) >{ > static if (T.length) > { > static if (is(typeof(T[0].ranges))) > return flatJoint(args[0].ranges, >joint(args[1..$]).ranges); > else > return flatJoint(args[0], joint(args[1..$]).ranges); > } > else > return Joint!()(); >} > >void main() >{ > > Joint!(uint[], uint[]) r1; > uint[] r2; > auto result = joint(r1, r2); > static assert(is(typeof(result) == Joint!(uint[], uint[], >uint[]))); >} > >Could be optimized to eliminate excessive copying. JointRetType is necessary because you can't use 'auto' (http://d.puremagic.com/issues/show_bug.cgi?id=2863) Without recursive calls: template StaticTuple(T...) { alias T StaticTuple; } struct Joint(T...) { T ranges; } template isJoint(T) { enum isJoint = is(typeof(T.ranges)); // or whatever means you choose to identify a Joint } private template JointArgs(T...) { static if (T.length) { static if (isJoint!(T[0])) alias StaticTuple!(typeof(T[0].ranges), JointArgs!(T[1..$])) JointArgs; else alias StaticTuple!(T[0], JointArgs!(T[1..$])) JointArgs; } else alias StaticTuple!() JointArgs; } private template targetIndexes(size_t index, T...) { static if (T.length) { static if (isJoint!(T[0])) alias StaticTuple!(index, targetIndexes!(index + typeof(T[0].ranges).length, T[1..$])) targetIndexes; else alias StaticTuple!(index, targetIndexes!(index + 1, T[1..$])) targetIndexes; } else alias StaticTuple!() targetIndexes; } Joint!(JointArgs!(T)) joint(T...)(T args) { typeof(return) ret; foreach (i, _i; T) { enum targetIndex = targetIndexes!(0, T)[i]; static if (isJoint!(T[i])) { foreach (j, _j; typeof(T[i].ranges)) ret.ranges[targetIndex + j] = args[i].ranges[j]; } else ret.ranges[targetIndex] = args[i]; } return ret; } void main() { auto r1 = Joint!(uint[], uint[])([1, 2], [3, 4]); uint[] r2 = [5, 6]; auto result = joint(r1, r2); static assert(is(typeof(result) == Joint!(uint[], uint[], uint[]))); assert (result.ranges[0] == [1u, 2][]); assert (result.ranges[1] == [3u, 4][]); assert (result.ranges[2] == [5u, 6][]); } | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply