simendsjo napisał: > While reading std.range, I though that a ducktyping design without > language/library support can be quite fragile. > > Consider the following example: > > import std.stdio; > > struct S > { > void shittyNameThatProbablyGetsRefactored() { }; > } > > void process(T)(T s) > { > static if( __traits(hasMember, T, "shittyNameThatProbablyGetsRefactored")) > { > writeln("normal processing"); > } > else > { > writeln("Start nuclear war!"); > } > } > > > void main() > { > S s; > process(s); > } > > > If you rename S's method, process() does something completely different > without a compile time error. By using interfaces this is avoided as the > rename would break the interface. > > Is there any idoms you can use to avoid stuff like this? Relying on > documentation doesn't seem like a good solution.
With template wizardry you can achieve an equivalent of interfaces for structs: struct Interface { bool foo(int, float); static void boo(float); ... } static assert (Implements!(S, Interface)); struct S { bool foo(int i, float f) { ... } static void boo(float f) { ... } ... } void process(T)(T s) if (Implements!(T, Interface)) { ... } And Implements!(T, I) is where the magic happens. It returns true if T has all the members of I with matching signatures. Not real interfaces, but close. Tomek