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);
}