www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Recursive template

reply "Eric" <eric makechip.com> writes:
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
Nov 15 2014
parent reply "anonymous" <anonymous example.com> writes:
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); }
Nov 15 2014
parent reply "Eric" <eric makechip.com> writes:
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); }
Nov 15 2014
parent "Chris Nicholson-Sauls" <ibisbasenji gmail.com> writes:
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."
Nov 15 2014