How to create TypeTuple/ExpressionTuple from tuple/tuples

Philippe Sigaud philippe.sigaud at gmail.com
Tue Aug 7 23:58:15 PDT 2012


On Wed, Aug 8, 2012 at 7:01 AM, Philippe Sigaud
<philippe.sigaud at gmail.com> wrote:

>> But that doesn't work for variadic templates, which is the OP's case:
>>
>> int foo(T...)(T t) { return 1; }
>> alias expander!foo efoo;  // error
>
> The template can easily be modified to deal with template functions,
> but in that case, you lose the parameter-type verification, for
> example if the function template has a constraint.

Like this:

/// Helper template to flatten a Tuple
template Expand(T)
{
    static if (isTuple!T)
        alias T.Types Expand;
    else
        alias T Expand;
}

/**
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)
{
   auto expander(Args...)(Args args)
   {
        static  if (isSomeFunction!fun)
            alias ParameterTypeTuple!fun Expanded;
        else
            alias staticMap!(Expand, Args) Expanded; // flatten the tuples

        Expanded expanded;
		
        /// Does the filling work: put values extracted from t in expanded
        void from(int index = 0, TupleOrNot...)(TupleOrNot t)
        {
            static if (TupleOrNot.length > 0)
            {
                static if (isTuple!(TupleOrNot[0])) // It's a tuple,
expand it ...
                {
                    expanded[index..index+TupleOrNot[0].length] = t[0].expand;
                    from!(index+TupleOrNot[0].length)(t[1..$]);
                }
                else // it's not a tuple, let it that way...
                {
                    expanded[index] = t[0];
                    from!(index+1)(t[1..$]); // ...and continue the recursion
                }
            }
        }
	
        from(args);
        return fun(expanded);
   }
}

int foo(Ts...)(Ts ts)
{
    return Ts.length;
}
	
void main()
{
   alias expander!foo efoo;

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


More information about the Digitalmars-d-learn mailing list