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

DoctorCaptain garble at harble.com
Sat Dec 14 14:38:19 PST 2013


>
> 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.
>
> 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

Thank you! This is excellent, and I'll make great use of your 
suggestions.

> I would think you can check the delegate signature directly 
> without decomposing it. Something like this:
>
> is(ReturnType!nextGen == T delegate (int))

This is a very concise way to do what I want to do, but this 
check cares about other attributes of the function/delegate, i.e. 
if the function or delegate is designated as pure or nothrow and 
those don't show up in the check, it will fail. As in:

auto nextGen()
{
     T genFunc(int x) nothrow
     {
         return 0;
     }
     return &genFunc;
}

genFunc will fail the is() check because the is check cares 
whether the delegate is nothrow or not. Since I want folks to be 
able to use my algorithm without caring about the implementation 
details, I need to provide constraints for the parameter lists 
and return types of their functions, but no constraints on 
whatever attributes they want to slap onto their functions. I 
will keep this in my toolbox, but I'll have to take the more 
long-winded approach this time around.

Thank you both!


More information about the Digitalmars-d-learn mailing list