On Thu, 21 Mar 2013 11:04:31 -0700 "H. S. Teoh" <hst...@quickfur.ath.cx> wrote: > > > - Calling popFront and then front returns the next element. > > How do you know if something is the "next element"? What if the range > is repeat(1)? > > > > - If range has length, then 'empty' returns true IFF popFront has > > been called at least 'myRange.length' times. > > This should also be easy to test. But it requires the ability to > instantiate the range with some given number of elements. So you still > need a range-specific function to create the range in the first place. >
What I had in mind was something like: void testForwardRange(R, E)(R range, E[] content) { // Deliberately not contraints, because this *is* a test, after all. // *Or* maybe it just auto-detects range type and leaves it // up to the user to check for "isForwardRange!R" or whatever. static assert(isForwardRange!R); static assert(is(ElementTypeOf!R == E)); static if(hasLength!R) assert(range.length == content.length); foreach(i; 0...content.length) { assert(range.front == content[i]); range.popFront(); } // More tests } unittest{ testForwardRange(createMyRangeSomehow(), [...expected elements...]); } > > > - Calling popFront on an empty range throws a RangeError. > > Is this part of the official requirement on ranges? I've been guilty > of writing ranges whose popFront are no-ops when the range is empty > (simply because for some ranges, it's a pain to explicitly check for > this and throw, when the popFront computation doesn't actually assume > anything about emptiness). > Actually, I'm not sure on that one. I would think that calling front on an empty range should throw. Or at least in a typical well-behaved range it should, even if it's not specifically stated as being technically mandatory. But in any case, it was only an example. > > > - Iterating via back/popBack yields the same elements as > > front/popFront, but in reverse order. > > Doesn't work on infinite ranges. :) (You *can* have infinite ranges > with two ends. There's no good reason to do that, of course, because > they are effectively just two infinite forward ranges stuck together > at their infinite ends, which is kinda pointless, but in theory, this > *can* happen.) > Naturally, the testing would be different on different types of ranges. The tester could auto-detect things like "isInfiniteRage" and "hasLength", and act accordingly. And of course, if you want to guarantee your range is indeed, for example, a "hasLength", then you can also just add "static assert(hasLength!MyRange);" alongside your call to the tester.