Generic method that takes in either delegate or function

Jonathan M Davis jmdavisProg at gmx.com
Wed Jan 12 00:47:16 PST 2011


On Wednesday 12 January 2011 00:21:54 %u wrote:
> Hi,
> 
> Is there any way to specify a parameter as "something that can be called
> with parameter types A, B, C and that returns a value of type D", without
> caring whether it's a delegate, a function, or an object that overloads
> opCall? (This might require the use of templates, but I still can't figure
> it out...)
> 
> Thank you!

Take this example from my proposed std.unittests which is currently under 
review:

void assertPred(alias pred, string msg = null, string file = __FILE__, size_t 
line = __LINE__, T...)
               (T args)
    if(isCallable!pred &&
       is(ReturnType!pred == bool) &&
       __traits(compiles, pred(args)) &&
       isPrintable!T)
{
    immutable result = pred(args);

    if(!result)
    {
        string argsStr;

        if(args.length > 0)
        {
            foreach(value; args)
                argsStr ~= format("[%s], ", to!string(value));

            argsStr.popBackN(", ".length);
        }
        else
            argsStr = "none";

        if(msg.empty)
            throw new AssertError(format("assertPred failed: arguments: %s.", 
argsStr), file, line);
        else
            throw new AssertError(format("assertPred failed: arguments: %s: %s", 
argsStr, msg), file, line);
    }
}


The combination of alias, isCallable, ReturnType, and __traits(compiles) does 
the trick. isCallable guarantees that pred is callable, but it doesn't care how. 
ReturnType guarantees that the return type is bool. And __traits(compiles, 
pred(args)) guarantees that pred can be called with the given arguments.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list