Thread overview
Recursive template
Nov 15, 2014
Eric
Nov 15, 2014
anonymous
Nov 15, 2014
Eric
November 15, 2014
Hi -

I've never designed a recursive template before, but I think
that would solve my problem.  What I would like is
someting like this:

class X(V, K...)
{
    // I want to declare a type based on K and V such
    // that for X!(V, int, string, double) the resulting
    // declaration would be:
    SomeType!(int, SomeType!(string, SomeType!(double, V))) var;

    // or put another way:
    SomeType!(K[0], SomeType!(K[1], SomeType(K[2], V))) var;
}

Can anyone give me some ideas on how to set up the declaration?

Thanks,

Eric
November 15, 2014
On Saturday, 15 November 2014 at 18:30:00 UTC, Eric wrote:
> Hi -
>
> I've never designed a recursive template before, but I think
> that would solve my problem.  What I would like is
> someting like this:
>
> class X(V, K...)
> {
>     // I want to declare a type based on K and V such
>     // that for X!(V, int, string, double) the resulting
>     // declaration would be:
>     SomeType!(int, SomeType!(string, SomeType!(double, V))) var;
>
>     // or put another way:
>     SomeType!(K[0], SomeType!(K[1], SomeType(K[2], V))) var;
> }
>
> Can anyone give me some ideas on how to set up the declaration?
>
> Thanks,
>
> Eric

It's pretty straight forward:

struct SomeType(K, V) {}

template X(V, K...)
{
     static if(K.length == 1)
         alias X = SomeType!(K[0], V);
     else static if(K.length > 1)
         alias X = SomeType!(K[0], X!(V, K[1 .. $]));
     else static assert(false);
}
November 15, 2014
Thanks!

-Eric


On Saturday, 15 November 2014 at 18:49:32 UTC, anonymous wrote:
> On Saturday, 15 November 2014 at 18:30:00 UTC, Eric wrote:
>> Hi -
>>
>> I've never designed a recursive template before, but I think
>> that would solve my problem.  What I would like is
>> someting like this:
>>
>> class X(V, K...)
>> {
>>    // I want to declare a type based on K and V such
>>    // that for X!(V, int, string, double) the resulting
>>    // declaration would be:
>>    SomeType!(int, SomeType!(string, SomeType!(double, V))) var;
>>
>>    // or put another way:
>>    SomeType!(K[0], SomeType!(K[1], SomeType(K[2], V))) var;
>> }
>>
>> Can anyone give me some ideas on how to set up the declaration?
>>
>> Thanks,
>>
>> Eric
>
> It's pretty straight forward:
>
> struct SomeType(K, V) {}
>
> template X(V, K...)
> {
>      static if(K.length == 1)
>          alias X = SomeType!(K[0], V);
>      else static if(K.length > 1)
>          alias X = SomeType!(K[0], X!(V, K[1 .. $]));
>      else static assert(false);
> }

November 16, 2014
Slightly simpler:


struct SomeType(K, V) {}

alias X(V)       = V;
alias X(V, K...) = SomeType!(K[0], X!(V, K[1 .. $]));




That's a recurring pattern to get used to: aliasing away to one of the parameters in a terminal and/or degenerate case.  Also: that an empty tuple matches no parameter "more exactly" than a tuple parameter.  I know that's not at all obvious, but it's what I've found to be the case; so when K[1 ..$] above ends up as the empty tuple (that is, when all K have been exhausted), the template for X(V) will be the "more exact match."