digitalmars.D.learn - Constraining template with function signature
- Carl Vogel (16/16) Jun 07 2016 Hi,
- Steven Schveighoffer (11/23) Jun 07 2016 The de-facto way to do this is to write a lambda, and check that you can...
- cy (28/33) Jun 09 2016 You could put all that stuff into one single template like this:
- Carl Vogel (6/8) Jun 12 2016 A very delayed thanks to both of you. It does seem like it would
Hi,
What's the best way, when using a Callable as a template
parameter, to constrain it by signature?
For example, if you have a function that sorts an array like so:
T[] sortArray(alias less, T)(T[] arr) { ... }
Then you know that you'd want `less` to have signature (T, T) ->
bool.
Now, I can use something like isCallable std.traits to make sure
the predicate is a Callable, and there are various function
traits in the module that I could combine with `is` clauses to
enforce the signature it seems, but that seems very clunky. Is
there a better way?
I note that I don't find many examples of this in phobos, so I'm
wondering if there actually is a good solution...
Thanks,
-c.
Jun 07 2016
On 6/7/16 9:42 PM, Carl Vogel wrote:
Hi,
What's the best way, when using a Callable as a template parameter, to
constrain it by signature?
For example, if you have a function that sorts an array like so:
T[] sortArray(alias less, T)(T[] arr) { ... }
Then you know that you'd want `less` to have signature (T, T) -> bool.
Now, I can use something like isCallable std.traits to make sure the
predicate is a Callable, and there are various function traits in the
module that I could combine with `is` clauses to enforce the signature
it seems, but that seems very clunky. Is there a better way?
I note that I don't find many examples of this in phobos, so I'm
wondering if there actually is a good solution...
The de-facto way to do this is to write a lambda, and check that you can
call the function inside the lambda, then check to see if that compiles.
e.g.:
if(is(typeof( { bool b = less(T.init, T.init)); } )))
The is(typeof( construct means "does this have a valid type". Should
only work if the call is sound.
You can also use __traits(compiles, but for some reason Phobos writers
prefer the is(typeof( mechanism (I remember someone saying there is a
difference, but I don't know what it is).
-Steve
Jun 07 2016
The other way is better, but since you asked... On Wednesday, 8 June 2016 at 01:42:55 UTC, Carl Vogel wrote:Now, I can use something like isCallable std.traits to make sure the predicate is a Callable, and there are various function traits in the module that I could combine with `is` clauses to enforce the signature it seems, but that seems very clunky. Is there a better way?You could put all that stuff into one single template like this: template isCompatibleCallable(alias Src, alias Dest) { static assert(isSomeFunction!Src || isCallable!Src, "Source is not callable"); static assert(isSomeFunction!Dest || isCallable!Dest, "Destination is not callable"); static assert(is(ParameterTypeTuple!Src == ParameterTypeTuple!Dest), "Type Tuples differ"); pragma(msg,ParameterStorageClassTuple!Src == ParameterStorageClassTuple!Dest); static assert(ParameterStorageClassTuple!Src == ParameterStorageClassTuple!Dest, "Storage classes differ"); static assert(is(ReturnType!Src == ReturnType!Dest), "Return type differs"); immutable bool isCompatibleFunction = true; } That works if you have a "default action" when the callable isn't specified, because you can match the Callable to the default one. So like... bool default_less(T)(T a, T b) { return a < b; } T[] sortArray(alias less = default_less!T, T)(T[] arr) if(isCompatibleCallable(less,default_less!T) { ... } But it's probably clearer to use that is(typeof({ how this function will be called })) trick.
Jun 09 2016
On Thursday, 9 June 2016 at 19:08:52 UTC, cy wrote:
But it's probably clearer to use that is(typeof({ how this
function will be called })) trick.
A very delayed thanks to both of you. It does seem like it would
be useful to have something like a hasSignature!(Fun, Ret,
Args...) defined in std.traits. But Steven's solution is pretty
good.
Thanks again!
Jun 12 2016









Steven Schveighoffer <schveiguy yahoo.com> 