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?

Reply via email to