On Tue, May 13, 2014 at 01:29:32PM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...] > I don't agree there was a consensus. I think empty should not have to > be called if it's already logically known that the range is not empty.
I only partially agree with this, up to the point where .empty has been checked previously, such as: void f1() { void f2(R)(R r) if (isInputRange!R) { doSomething(r.front); } auto r = makeMeARange(); if (!r.empty) f2(r); ... } 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); } [...] > In any case, I think generic code for an unknown range type in an > unknown condition should have to call empty, since it cannot logically > prove that it's not. [...] In my mind, *all* range-based code is generic. If you need to depend on something about your range beyond what the range API guarantees, then you should be using the concrete type rather than a template argument, which means that your code is no longer range-based code -- it's operating on a concrete type. (Of course, if the concrete type implements the range API, then there's nothing wrong with using range API methods, but one shouldn't be under the illusion that one is writing range-based code. It is type-dependent code that just happens to have range-based methods. If the code will break if the range is substituted by a different range that doesn't have the same guarantees (outside of what the range API specifies), then it's not range-based code.) T -- Many open minds should be closed for repairs. -- K5 user