https://issues.dlang.org/show_bug.cgi?id=15027
--- Comment #1 from Kenji Hara <[email protected]> --- It's hard to resolve issue with current D language features. Reduced case: ---- void popFront(T)(ref T[] a) { a = a[1..$]; } enum bool isInputRange(R) = is(typeof( { R r; r.popFront(); })); struct DirEntry { @property string name() { return ""; } alias name this; } pragma(msg, isInputRange!DirEntry); // prints 'false' pragma(msg, isInputRange!(typeof(DirEntry.init.name))); // prints 'true' bool isDir(R)(R r) if (isInputRange!R) { return true; } void main() { DirEntry de; bool c = isDir(de); // [A] cannot match! } At line [A], `isDir` template function tries to deduce R from the function argument `de`. Although the type DirEntry matches R and deduction succeeds, IFTI fails to satisfy the template constraint isInputRange!R. What we need is R will be deduced to string, which is the type of alias this expression `de.name`. Sadly template constraint evaluation happens *after* the each template parameter deductions succeeds. In other words, currently we have no way to reject the match of R with DirEntry. A workaround code would be something like: bool isDir(Range)(Range range) if (isInputRange!Range || is(StringTypeOf!Range)) { static if (is(StringTypeOf!Range) && isAggregate!Range) alias R = StringTypeOf!Range; else alias R = Range; static bool isDirImpl(R r) { ... } return isDirImpl(range); // expect alias this expansion on function arguments } However, it requires redundant copy and destruction of DirEntry. So it would not become a solution. --
