wrong isInputRange design
rumbu via Digitalmars-d
digitalmars-d at puremagic.com
Sat Dec 3 03:52:00 PST 2016
import std.range.primitives: isInputRange;
void test(R)(ref R range) if (isInputRange!R)
{
auto c = r.front; //Error: no property 'front' for type
'string'
}
string s = "some string";
test(s);
The problem is that isInputRange will always return true for
string types (because it will check the availability of front,
popFront, empty through the entire std.range.primitives module.
Since the only thing that was imported is std.range.primitives:
isInputRange, front is not available for strings.
OK, the simple resolution is to import entirely
std.range.primitives, but the source of the problem was another:
I tried to define two overloads, one accepting strings, and one
accepting ranges;
import std.range.primitives: isInputRange, ElementType;
import std.traits: isSomeChar;
void foo(C)(const(C)[] array) if (isSomeChar!C)
{
//this will be never called
}
void foo(R)(ref R range) if (isInputRange!R &&
isSomeChar!(ElementType!R))
{
//this will be always called
//any call to range.front, range.empty and so on will result
in error
}
foo(somestring)
I expect foo!string to be called instead of foo!Range, because in
my context isInputRange!string should return false. Instead, my
context is hijacked by the definitions spread along
std.range.primitives module.
The workaround I found is to define the second overload like this:
void foo(R)(ref R range) if (isInputRange!R && !isSomeString!R &&
isSomeChar!(ElementType!R))
More information about the Digitalmars-d
mailing list