OK, here's what I have now - two templates that are self contained and work well:

The first uses opDispatch to dispatch to a member. The second is a simple string function that generates the appropriate code. As discussed the latter composes but the former doesn't.

mixin template dispatchToMember(alias member, methods...)
{
    import std.algorithm : among;
    import std.traits : ParameterTypeTuple;
    template opDispatch(string sym)
    if ((methods.length == 0 || sym.among(methods)))
    {
auto ref opDispatch(ParameterTypeTuple!(__traits(getMember, member, sym)) args)
        {
            return __traits(getMember, member, sym)(args);
        }
    }
}

string forwardToMember(string member, string[] funs...)
{
string result = " import std.traits : hasMember, ParameterTypeTuple;\n";
    foreach (fun; funs)
    {
        result ~= "
    static if (hasMember!(typeof("~member~"), `"~fun~"`))
    auto "~fun~"(ParameterTypeTuple!(typeof("~member~"."~fun~")) args)
    {
        return "~member~"."~fun~"(args);
    }\n";
    }
    return result;
}


Andrei

Reply via email to