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