digitalmars.D.learn - How to obtain certain traits of delegates returned by functions in
- DoctorCaptain (24/24) Dec 14 2013 My question is hopefully short and straightforward to answer, but
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (53/72) Dec 14 2013 function.
- DoctorCaptain (23/82) Dec 14 2013 This is a very concise way to do what I want to do, but this
- Philippe Sigaud (26/26) Dec 14 2013 I have 3 comments (if you're still reading this thread :) )
- Jacob Carlborg (4/23) Dec 15 2013 Hmm, there might be a way to strip all the attributes of a function.
- TheFlyingFiddle (16/18) Dec 15 2013 template strip(T) if(is(T == delegate))
- TheFlyingFiddle (1/2) Dec 15 2013 Typo should be stripped.
- Jacob Carlborg (6/10) Dec 14 2013 I would think you can check the delegate signature directly without
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 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!
Dec 14 2013
On 12/14/2013 11:53 AM, DoctorCaptain wrote:> My question is hopefully short and straightforward to answer, but it'salso 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 thefunction.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/ef1a970fMost 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
Dec 14 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. AliThank 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!
Dec 14 2013
I have 3 comments (if you're still reading this thread :) ) First, you could let nextGen determine the return type. Since the template know that nextGen returns an int delegate(int), there is no need for the user to provide the 'int' parameter. So user code could become: void main(string[] argv) { auto exFunc = &exT!(nextGen).exFunc; // <- here exFunc(); } Second, you could have exT return (become) the function itself, saving you the trouble to call it with exT!(...).exFunc In that case, exT could be a template function. Third, you can also use it directly, like this: // First call: exT!(nextGen)(); If you still want to name it other wise, you can use and alias: // Second call: alias myFunc1 = exT!(nextGen); myFunc1(); Or use a function pointer, as in your initial code: // Third call: auto myFunc2 = &exT!(nextGen); myFunc2(); Which gives us shorter developer and user code. See here. http://dpaste.dzfl.pl/63a220cf
Dec 14 2013
On 2013-12-14 23:38, DoctorCaptain wrote: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.Hmm, there might be a way to strip all the attributes of a function. -- /Jacob Carlborg
Dec 15 2013
On Sunday, 15 December 2013 at 10:44:38 UTC, Jacob Carlborg wrote:Hmm, there might be a way to strip all the attributes of a function.template strip(T) if(is(T == delegate)) { alias stripped = ReturnType!T delegate(ParameterTypeTuple!T); } template strip(T) if(is(T == function)) { alias stripped = ReturnType!T function(ParameterTypeTuple!T); } unittest { alias a = void delegate(int) nothrow pure const; alias b = void delegate(int); static assert(is(stripped!a == stripped!b)); } This should do the trick.
Dec 15 2013
template strip(T) if(is(T == delegate))Typo should be stripped.
Dec 15 2013
On 2013-12-14 20:53, DoctorCaptain wrote: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!I would think you can check the delegate signature directly without decomposing it. Something like this: is(ReturnType!nextGen == T delegate (int)) -- /Jacob Carlborg
Dec 14 2013