On Wednesday, 30 December 2015 at 15:51:23 UTC, default0 wrote:
Yeah, I misinterpreted the "E : <stuff>" to mean "E is or
inherits from <stuff>", rechecking the argument deduction rules
for templates I think this instead means "E should be deduced
Sort of.. it means "if E can be implicitly converted to <stuff>".
All of this stuff:
is(E : ElementType!(ElementType!RoR))
(doesn't copy paste well, I gotta fix my html a bit)
Could be rewritten as
"ror is an input ranges of input ranges and sep can be implicitly
converted to the type of ror's inner range's elements."
Or something like that.
So given: join([[1L], [2L]], 1);
Constraint clause 1: isInputRange!RoR passes because an array,
this is long is an input range.
Constraint clause 2: ElementType!RoR is long because
ElementType basically trips off the outer  from RoR's type
(basically), which is long.
Unqual!T trims off qualifiers like const, immutable, etc.
Basically it takes the type out of parenthesis. There are none of
that here, so long is still long.
Finally, the clause passes because long is an input range.
Constraint clause 3: asks if E, which in this example is
typeof(1), which is `int`, is implicitly convertible to the type
of RoR with *two* layers of  trimmed off. RoR was long so
ElementType!ElementType!(long) returns `long`.
Since `int` implicitly converts to `long` (every int value is a
valid long value too), this constraint passes.
If it said is(E == same_stuff), it would fail because int !=
long. But since it is is(E : stuff), it passes because that
allows implicit conversions.
I'll be writing an article with content like this that links from
the keyword `if` in those prototypes (Currently it links to
dlang.org's spec page but that's not as useful to api doc readers
I also plan to put a link to this under a "D Concepts" sub-header
in the See Also section. Yes, on every page it is used. If
someone lands here from a search engine, they shouldn't be
assumed to already know everything! And it is hard to search for
"dlang function if"...