On 11/09/12 07:41, Nick Sabalausky wrote: > Of course, it'd be even nicer still to have all this wrapped up in > some language sugar (D3? ;) ) and just do something like: > > struct interface InputRange { > // ... *declare* .empty, .front, .popFront here > } > > struct interface ForwardRange : InputRange { > // ... *declare* .save here > } > > struct MyForwardRange : ForwardRange { > // ... define .empty, .front, .popFront, .save here > // Actually validated by the compiler > } > > Which would then amount to what we're doing by hand up above. So kinda > like Go, except not error-prone and ducky and all shitty.
This would actually be backwards compatible and also relatively forward compatible - does not need to wait for a D3. However, while it's a step in the right direction, doing it like that would be to limiting. Compare with: interface template InputRange(T) { enum InputRange = __traits(compiles, {T r; /* check the i/f here */}); } struct MyInputRange : InputRange { enum empty = false; enum front = 42; void popFront() {} } Ie requiring a certain interface to be present is fine, requiring a certain set of function signatures is too restrictive (and could still be done inside the interface-template when necessary). I used "interface-templates" because this feature should not clash with /normal/ struct inheritance, once that one emerges. All the boilerplate in the InputRange template above could be made implicit and it could then look like this: interface template InputRange(T) { T r; bool e = r.empty; r.popFront(); auto f = r.front; } else throw("Not an input range"); // "static throw", "assert", whatever. These i/f templates would also be useful in places where the current 'isInputRange' hack is used; would significantly improve both readability and error reporting (that's the reason for the else clause). artur