On Friday, 24 July 2015 at 04:42:59 UTC, Walter Bright wrote:

Consider the following:

    int foo(T: hasPrefix)(T t) {
       t.prefix();    // ok
       bar(t);        // error, hasColor was not specified for T
    }

    void bar(T: hasColor)(T t) {
       t.color();
    }

Now consider a deeply nested chain of function calls like this. At the bottom, one adds a call to 'color', and now every function in the chain has to add 'hasColor' even though it has nothing to do with the logic in that function. This is the pit that Exception Specifications fell into.

I'm a little confused here. I seem to be of the belief that D's interfaces can accomplish virtually the same thing as Rust's traits. In your example, if the type you pass to foo also inherits from hasColor, then it shouldn't be a problem.

I fleshed out what you said a bit more with respect to D's interfaces, adding another part to the chain as well. Obviously baz in my example can't call objects from classes A and B because they don't inherit from hasAlt. Isn't this the behavior you would want? Another alternative is to have hasAlt inherit from hasColor and hasPrefix.


import std.stdio : writeln;

interface hasColor
{
        final void color()
        {
                writeln("calling color");
        }
}

interface hasPrefix
{
        final void prefix()
        {
                writeln("calling prefix");
        }
}

interface hasAlt
{
        final void alt()
        {
                writeln("calling alt");
        }
}

class A : hasColor { }

class B : A, hasPrefix { }

class C : B, hasAlt { }

void foo(T: hasColor)(T t)
{
        t.color();
}

void bar(T: hasPrefix)(T t)
{
        t.prefix();
        foo(t);
}

void baz(T: hasAlt)(T t)
{
        t.alt();
        bar(t);
}

void main()
{
        auto a = new A;
        foo(a);
        auto b = new B;
        foo(b);
        bar(b);
        auto c = new C;
        foo(c);
        bar(c);
        baz(c);
}

Reply via email to