When does take modify the underlying iterator?

cy via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Aug 16 14:01:14 PDT 2016


InputRanges that are not ForwardRanges seem to lack a possibly 
crucial operation. I want to start with an arbitrary range, take 
1 from it, then process the rest. But there doesn't seem to be 
any way to do that, because there's no way to tell whether "take" 
will advance the range, or whether it will leave the range as-is.

When you know a range implements front, empty, and popFront, and 
you take from that range, there seems to be a secret requirement 
that the iterator supports save() via copy constructor. And if it 
doesn't... your program just breaks silently when you drop 
elements that haven't been processed yet.

Is there some way around that, that I'm not aware of?

struct CertainlyNotAForwardRange(A) {
	static int i = 0;
	A a;
	auto front() {
		return a[i];
	}
	auto empty() {
		return i == a.length;
	}
	auto popFront() {
		++i;
	}
}

struct SecretlyForwardRange(A) {
	A a;
	int i = 0;
	auto front() {
		return a[i];
	}
	auto empty() {
		return i == a.length;
	}
	auto popFront() {
		++i;
	}
}

auto failhard(T)(T iter) {
	import std.stdio;
	import std.range: take, drop;
	import std.array: array;

	writeln("We have some range:");
	writeln(typeid(T));
	writeln("We take 1 from it...");
	writeln(iter.take(1));
	writeln("The rest of the range has:");
	writeln(iter.drop(1).array);
	writeln("");
}	

void main() {
	auto arr = [0, 1, 2, 3];
	failhard(arr);
	failhard(SecretlyForwardRange!(typeof(arr))(arr));
	failhard(CertainlyNotAForwardRange!(typeof(arr))(arr));
}



More information about the Digitalmars-d-learn mailing list