On Thu, 8 Nov 2012 20:17:24 -0800 "H. S. Teoh" <hst...@quickfur.ath.cx> wrote: > > Actually, I just thought of a solution to the whole duck-typing range > thing: > > struct MyRange { > // Self-documenting: this struct is intended to be a > // range. > static assert(isInputRange!MyRange, > "Dude, your struct isn't a range!"); // > asserts > > On Fri, 09 Nov 2012 05:18:59 +0100 "Adam D. Ruppe" <destructiona...@gmail.com> wrote: > > Just a note, of course it still wouldn't *force*, but maybe it'd > be a good habit to start writing this: > > struct myrange {...} > static assert(isInputRange!myrange); >
Those are only half-solutions as they only prevent false-negatives, not false-positives. Plus, there's nothing to prevent people from forgetting to do it in the first place. I outlined and implemented a proof-of-concept for a full solution middle of last year: http://www.semitwist.com/articles/EfficientAndFlexible/MultiplePages/Page5/ The basic gist (and there's definitely still room for plenty of improvement): // The General Tool: string declareInterface(string interfaceName, string thisType) { return ` // Announce what interface this implements. static enum _this_implements_interface_`~interfaceName~`_ = true; // Verify this actually does implement the interface static assert( is`~interfaceName~`!(`~thisType~`), "This type fails to implement `~interfaceName~`" ); `; } // Sample usage: template isFoo(T) { immutable bool isFoo = __traits(compiles, (){ T t; static assert(T._this_implements_interface_Foo_); t.fooNum = 5; int x = t.fooFunc(""); // Check everything else here }); } struct MyFoo { // Can probably be more DRY with fancy trickery mixin(declareInterface("Foo", "MyFoo")); int fooNum; int fooFunc(string a) {...} } What I'd really like to see is a way to implement declareInterface so that the isFoo is replaced by an ordinary "interface Foo {...}", which MyFoo's members are automatically checked against. I suspect that should be possible with some fancy metaprogramming-fu.