On Thursday, 23 July 2015 at 20:52:46 UTC, Walter Bright wrote:
> My point was about the fact that `isInputRange`
> and `InputRangeObject` are the same entities in Rust, simply
interpreted
> differently by compiler depending on usage context.
I understand.
Ok, sorry, it wasn't clear from the response context :)
I don't think the test for struct and class is necessary. It
can be just:
void foo(T)() if (Matches!(T, Interface)) { ... }
as opposed to:
void foo(T : Interface)() { ... }
Correct indeed, though I don't feel it is much of a difference
considering how common such code is (remember that you endorse
ranges as The Way for designing APIs!)
> - much better error messages: trying to use methods of T not
defined by a trait
> will result in compile-time error even without instantiating
the template
The error messages will occur at compile time and will be the
same if you write a unit test to instantiate the template. As I
wrote earlier, I don't really understand the need to ship
template source code that has never been instantiated.
1)
It does not protect from errors in definition
void foo (R) (Range r)
if (isInputRange!Range)
{ r.save(); }
unittest
{
SomeForwardRange r;
foo(r);
}
This will compile and show 100% test coverage. Yet when user will
try using it with real input range, it will fail.
2)
There is quite a notable difference in clarity between error
message coming from some arcane part of function body and
referring to wrong usage (or even totally misleading because of
UFCS) and simple and straightforward "Your type X does not
implement method X necessary for trait Y"
3)
Coverage does not work with conditional compilation:
void foo (T) ()
{
import std.stdio;
static if (is(T == int))
writeln("1");
else
writeln("2");
}
unittest
{
foo!int();
}
$ dmd -cov=100 -unittest -main ./sample.d