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