How to obtain certain traits of delegates returned by functions in template constraints?

Ali Çehreli acehreli at yahoo.com
Sat Dec 14 13:58:19 PST 2013


On 12/14/2013 11:53 AM, DoctorCaptain wrote:> My question is hopefully 
short and straightforward to answer, but it's
 > also a two-parter.
 >
 > I am working on a template that generates a function that implements an
 > algorithm using several helper functions that are provided to the
 > template by the user. I would like to add constraints to the template to
 > restrict what functions the user can attempt to instantiate the template
 > with, as the algorithm implemented by a function in the template has
 > specific requirements. One of the functions required by the template
 > needs to return a delegate so that it can be used as a generator of
 > sorts. In any case. I have the ability to check the return type, arity,
 > and parameter list of a function in the constraints of the template, and
 > I can also check the return type of the delegate returned by the 
function.
 >
 > So, first, how do I check the arity of and retrieve a parameter type
 > tuple of the delegate returned by the function? Hopefully the example
 > code in the following dpaste will fully illustrate my question:
 >
 > http://dpaste.dzfl.pl/ef1a970f

Most uses of the 'is expression' allows using a specifier to name the 
entity that matched. So, inserting ReturnedDelegate in your '== 
delegate' line gives the name ReturnedDelegate to the delegate.

That name can be used further:

template exT(T, alias nextGen)
     if (
         // Ensure nextGen is a callable entity
            isCallable!nextGen == true
         // Ensure nextGen returns a delegate
         && is(ReturnType!nextGen ReturnedDelegate == delegate) // <--
         // Ensure nextGen takes one argument
         && arity!nextGen == 1
         // Ensure that argument is of type T
         && is(ParameterTypeTuple!nextGen[0] == T)
         // Ensure the returned delegate returns type T
         && is(ReturnType!ReturnedDelegate == T)
         // Ensure the arity and parameter type of the delegate
		// && arity!ReturnedDelegate == 1
         && ParameterTypeTuple!ReturnedDelegate.length == 1 // <--
         && is(ParameterTypeTuple!ReturnedDelegate[0] == int) // <--
         )
{
     // ...
}

However, since arity() takes an alias but ReturnedDelegate is a type, I 
could not make it work. So, I use the length of the parameter type tuple 
instead.

 > Second, can I get the level of thoroughness I am going for in these
 > constraints checks with fewer actual checks? As in, is there a more
 > straightforward way to do these checks without sacrificing any of them?
 >
 > Thank you for any and all insight!

You can put all of those checks into a template and pass T and nextGen 
to it:

template exT(T, alias nextGen)
     if SatisfiesMyConditions!(T, nextGen)
{
     // ...
}

I haven't attempted writing it but it will be similar to the following 
syntax:

template canFlyAndLand(T)
{
     enum canFlyAndLand = is (typeof(
     {
         T object;
         object.prepare();  // should be preparable for flight
         object.fly(1);     // should be flyable for a certain distance
         object.land();     // should be landable
     }()));
}

I've copied that example from under the "Named constraints" section at

   http://ddili.org/ders/d.en/templates_more.html

Phobos implementation has many examples of that as well.

Ali



More information about the Digitalmars-d-learn mailing list