How to create TypeTuple/ExpressionTuple from tuple/tuples

Philippe Sigaud philippe.sigaud at gmail.com
Tue Aug 7 11:55:03 PDT 2012


On Tue, Aug 7, 2012 at 7:35 PM, Andrej Mitrovic
<andrej.mitrovich at gmail.com> wrote:


> Yeah. It's somewhat possible to use a helper function for multiple
> TypeTuples, but the problem is D functions cannot return language
> tuples (only TypeTuple from std.typecons which is what the tuple()
> call creates) so you would always need to call "expand" before the
> function call, e.g.:

You can also take the 'dual' of your solution and have a template that
makes a function automatically expand tuples:

alias expander!foo efoo;

// efoo is a function that accepts tuples and automatically cracks
them open for you, and then pass them to foo

auto result = efoo(tuple(1,2), "abc", tuple('a', 3.14));
assert(result = foo(1,2,"abc", 'a', 3.14));

The same idea could be use to have a function 'expand' any
user-defined type, be they structs or classes, by applying .tupleof on
them.
The code for expander is a little bit involved, I'm afraid, I had to
use a helper struct.


import std.traits;
import std.typecons;

struct Fill(Expanded...)
{
    Expanded expanded;
    void from(int index = 0, TupleOrNot...)(TupleOrNot args)
    {
        static if (TupleOrNot.length > 0)
        {
            static if (isTuple!(TupleOrNot[0])) // It's a tuple, expand it ...
            {
                expanded[index..index+TupleOrNot[0].length] = args[0].expand;
                from!(index+TupleOrNot[0].length)(args[1..$]); // ...
and continue the recursion
            }
            else // it's not a tuple, let it that way...
            {
                expanded[index] = args[0];
                from!(index+1)(args[1..$]); // ...and continue the recursion
            }
        }
    }
}


/**
Take a function fun and return a transformed function that will expand
std.typecons.Tuple's provided as arguments and let other args untouched
*/
template expander(alias fun) if (isSomeFunction!fun)
{
   ReturnType!fun expander(Args...)(Args args)
   {
        Fill!(ParameterTypeTuple!fun) f; // prepare the future arguments
        f.from(args); // does the expansion job, the arguments are
stored in f.expanded
        return fun(f.expanded);
   }
}

void main()
{
    int foo(int i, double d, string s, char c) { return i + cast(int)d
+ s.length + (c - '0');}
    alias expander!foo efoo;

    writeln( foo(1, 3.14, "abc", 'a') );
    writeln( efoo(tuple(1, 3.14, "abc", 'a')) );
    writeln( efoo(tuple(1, 3.14), "abc", 'a') );
    writeln( efoo(tuple(1, 3.14), tuple("abc", 'a')) );
}


More information about the Digitalmars-d-learn mailing list