On 13.5.2014. 19:40, H. S. Teoh via Digitalmars-d wrote: > On Tue, May 13, 2014 at 01:29:32PM -0400, Steven Schveighoffer via > Digitalmars-d wrote: > [...] > Even in this case, I'd put an in-contract on f2 that verifies that the > range is indeed non-empty: > > ... > void f2(R)(R r) > if (isInputRange!R) > in { assert(!r.empty); } > body { > doSomething(r.front); > } > > [...]
This is a potential issue because if it turns out that empty _must_ be called than the author could put the front population logic inside empty. Consider: struct R { bool empty () { front = 1; return false; } int front = 0; void popFront () { front = 0; } } This is a valid code if empty _must_ be called, but it will behave differently if passed to f2 in case asserts are compiled out. In case asserts are compiled out empty is never called and front in never populated. Because of this I think that it is necessary to document range behavior.