On Wednesday, 30 August 2017 at 22:52:41 UTC, Adam D. Ruppe wrote:
On Wednesday, 30 August 2017 at 20:47:12 UTC, EntangledQuanta wrote:
This is quite surprising!

In the new version pending release (scheduled for later this week), we get a new feature `static foreach` that will let you loop through the types you want and declare all the functions that way.

When it is released, we'll have to take a second look at this problem.

I've already implemented a half ass library solution. It works, but is not robust. The compiler can and should do this!




string OverLoadTemplateDefinition(string name, alias func, T...)()
{
        import std.string;
        string str;
foreach(t; T) str ~= ((func!t).stringof).replace("function(", name~"(")~";\n";
        return str;
}

string OverLoadTemplateMethod(string name, alias func, T...)()
{
        import std.traits, std.algorithm, std.meta, std.string;

        alias RT(S) = ReturnType!(func!S);
        alias PN(S) = ParameterIdentifierTuple!(func!S);
        alias P(S) = Parameters!(func!S);
        alias PD(S) = ParameterDefaults!(func!S);

        string str;
        foreach(t; T)
        {
                str ~= (RT!t).stringof~" "~name~"(";
                foreach(k,p; P!t)
                {
                        auto d = "";
                        static if (PD!t[k].stringof != "void")
                                d = " = "~(PD!t)[k].stringof;
                        str ~= p.stringof~" "~(PN!t)[k]~d;
                        if (k < (P!t).length - 1)
                                str ~= ", ";
                }
                
                str ~= ") { _"~name~"(";
                foreach(k, n; PN!t)
                {
                        str ~= n;
                        if (k < (P!t).length - 1)
                                str ~= ", ";
                }
                str ~= "); }\n";
        }
        return str;
}


They are basically the generic version of what Jonathan implemented by hand.

In the interface:

private alias _Go(T) = void function();

mixin(OverLoadTemplateDefinition!("Go", _Go, int, short, float, double)());

In class:

mixin(OverLoadTemplateMethod!("Go", _Go, int, short, float, double)());

protected final void _Go(T)()
        {
....
        }


The alias simply defines the function that we are creating. The mixin OverLoadTemplateDefinition creates the N templates.

in the class, we have to do something similar but dispatch them to the protected _Go... very similar to what Jonathan did by hand. But the code to do so is not robust and will break in many cases because I left a lot of details out(linkage, attributes, etc).

It is a proof of concept, and as you can see, it is not difficult. The compiler, and anyone that has a decent understanding of the internals of it, should be able to implement something quite easily.

Maybe it is also possible to use OpCall to do something similar?

I'd like to reiterate that this is not an insolvable problem or an NP problem. It is quite easy. If we require restricting the types to a computable set, it is just simple overloading and templatizing to reduce the complexity.

Having the compiler to this can reduce the noise and increase the robustness and also provide a nice feature that it currently does not have, but should.

Using templates with inheritance is a good thing, It should be allowed instead of blinding preventing all cases when only one case is uncomputable. The logic that some are using is akin to "We can't divide by 0 so lets not divide at all", but of course, division is very useful and one pathological case doesn't prevent all other cases from being useful.

Reply via email to