How to implement predicates for Filter!(Pred, Tuple)

Timon Gehr timon.gehr at gmx.ch
Fri Nov 11 09:20:22 PST 2011


On 11/11/2011 11:04 AM, Tobias Pankrath wrote:
> I've written a Filter-Template, which implements the well-known function for
> template arguments:
>
> -----
> template Filter(alias SPred, E...)
> {
>      static if(E.length == 0) {
>          alias TypeTuple!() Filter;
>      }
>      else
>      {
>          static if(SPred!(E[0]))
>          {
>              alias TypeTuple!(E[0], Filter!(SPred, E[1..$])) Filter;
>          }
>          else
>          {
>              alias Filter!(SPred, E[1..$]) Filter;
>          }
>      }
> }
> ------
>
> This works just fine:
> ---
> template IsEqual(int This)
> {
>      template IsEqual(int That)
>      {
>          enum bool IsEqual = This == That;
>      }
> }
>
> static assert(is(Filter!(IsEqual!5, 5,1,5,1,5) == TypeTuple!(5, 5, 5)));
> ---
>
> However I can't use it directly, for example like this:
>> pragma(msg, IsEqual!(5)!5);
>
> However if I wouldn't rely on the ETT, and use a different name for the
> inner
> template, it will work.
>
> ---
> template IsEqual(int This)
> {
>    template Pred(int That)
>    {
>      enum bool Pred = This == That;
>    }
> }
>
> pragma(msg, IsEqual!(5).Pred!(5));
> ---
>
> But that will make IsEqual less elegant to use in conjunction with filter.
> So, is there a way to elegantly use one template in both cases? Otherwise I
> would declare two versions:
> one with a single and one with two parameter.
>
> --
> Tobias
>

This is a sketch of how I would approach your problem. The "Curry" 
template automatically creates the nested template version from an 
unnested one. You are then allowed to use both IsEqual!(val) and 
IsEqual!(val1, val2).


template IsEqual(int This, int That){
	enum IsEqual = This == That;;
}
mixin(Curry!IsEqual);

static assert(IsEqual!(1,1));
static assert(!IsEqual!(1,2));

alias IsEqual!(1) IsEqual1;
static assert(IsEqual1!1);
static assert(!IsEqual1!2);


// implementation of Curry:

import std.array, std.string;

template Curry(alias x){
	enum Curry = curryImpl(x.stringof);
}
private string curryImpl(string decl){
	auto psta = decl.indexOf("(");
	auto name = decl[0..psta];
	auto pstr = decl[psta+1..$-1];
	auto prms = pstr.split(",");
	string r;
	foreach(prm; prms) r ~= "template " ~ name ~ "("~prm~"){";
	r ~= "enum " ~ name ~ " = ." ~ name ~ "!("; // TODO: make this work for 
templates not at module scope
	foreach(prm; prms) r ~= prm[prm.indexOf(" ")+1..$]~",";
	r ~= ");";
	foreach(prm; prms) r~="}";
	return r;
}









More information about the Digitalmars-d-learn mailing list