Struct Flattening
Max Samukha
samukha at voliacable.com.removethis
Thu Apr 23 03:08:50 PDT 2009
On Thu, 23 Apr 2009 10:45:01 +0200, Max Samukha
<samukha at 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][]);
}
More information about the Digitalmars-d
mailing list