On Saturday, 3 December 2016 at 11:52:00 UTC, rumbu wrote:
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))
Is that the exact code? isInputRange checks to see if the type
has "front" defined.
https://github.com/dlang/phobos/blob/v2.072.0/std/range/primitives.d#L162
Also "string" is just an alias of an array, "immutable(char)[]".
So an array should have "front" defined. Can you post more code?