Constraining template with function signature

cy via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jun 9 12:08:52 PDT 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.


More information about the Digitalmars-d-learn mailing list