Deprecate InputRange source for OutputRanges
An output range for E won't be automatically an output range for [E] anymore. The same, an output range for [E] won't be automatically an output range for E. Automatic E <-> [E] conversion seems to be a nice feature at first glance, but it causes much ambiguity. 1) If I want that my output range accepts only UTF-8 strings but not single characters (because it could be only part of a code point and look like broken UTF-8 without the remaining code units), I can't do it because an OutputRange(R, E) can't distinguish between char and string. 2) Here is an example from 2013: import std.range; import std.stdio; Appender!(const(char)[][]) app; put(app, "aasdf"); put(app, 'b'); writeln(app.data); This outputs: ["aasdf", "\0"]. Whether it is a common case or not, such code just shouldn't compile.
This commit is contained in:
parent
bf197a6554
commit
0c8f1eb4ce
@ -309,7 +309,7 @@ void swap(T)(ref T a, ref T b) @trusted
|
||||
* $(D_PARAM source) elements.
|
||||
*/
|
||||
Target copy(Source, Target)(Source source, Target target)
|
||||
if (isInputRange!Source && isOutputRange!(Target, Source))
|
||||
if (isInputRange!Source && isOutputRange!(Target, ElementType!Source))
|
||||
in
|
||||
{
|
||||
static if (hasLength!Source && hasLength!Target)
|
||||
|
@ -798,15 +798,13 @@ template isRandomAccessRange(R)
|
||||
/**
|
||||
* Puts $(D_PARAM e) into the $(D_PARAM range).
|
||||
*
|
||||
* $(D_PSYMBOL R) should be an output range for $(D_PARAM E). It doesn't mean
|
||||
* that everything $(D_PARAM range) is an output range for can be put into it,
|
||||
* but only if one of the following conditions is met:
|
||||
* $(D_PSYMBOL R) should be an output range for $(D_PARAM E), i.e. at least one
|
||||
* of the following conditions should met:
|
||||
*
|
||||
* $(OL
|
||||
* $(LI $(D_PARAM R) defines a `put`-method for $(D_PARAM E))
|
||||
* $(LI $(D_PARAM e) can be assigned to $(D_INLINECODE range.front))
|
||||
* $(LI $(D_PARAM e) can be put into $(D_PARAM range) using
|
||||
* $(D_INLINECODE range(e))
|
||||
* $(LI $(D_PARAM e) can be assigned to $(D_INLINECODE range.front))
|
||||
* )
|
||||
* )
|
||||
*
|
||||
@ -894,36 +892,28 @@ void put(R, E)(ref R range, auto ref E e)
|
||||
* $(TH Scenario)
|
||||
* )
|
||||
* $(TR
|
||||
* $(TD r.put(e))
|
||||
* $(TD $(D_PARAM R) defines `put` for $(D_PARAM E).)
|
||||
* )
|
||||
* $(TR
|
||||
* $(TD r.front = e)
|
||||
* $(TD $(D_PARAM R) is an input range, whose element type is
|
||||
* $(D_PARAM E) and `front` is an lvalue.)
|
||||
* )
|
||||
* $(TR
|
||||
* $(TD r(e))
|
||||
* $(TD $(D_PARAM R) defines `opCall` for $(D_PARAM E).)
|
||||
* )
|
||||
* $(TR
|
||||
* $(TD for (; !e.empty; e.popFront()) r.put(e.front) $(BR)
|
||||
* for (; !e.empty; e.popFront(), r.popFront())
|
||||
* r.front = e.front $(BR)
|
||||
* for (; !e.empty; e.popFront()) r(e.front)
|
||||
* )
|
||||
* $(TD $(D_PARAM E) is input range, whose elements can be put into
|
||||
* $(D_PARAM R) according to the rules described above in this table.
|
||||
* )
|
||||
* $(TD r.front = e)
|
||||
* $(TD $(D_PARAM R) is an input range with assignable elements of type
|
||||
* $(D_PARAM E).)
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* Output ranges don't have element type (so $(D_PSYMBOL ElementType) returns
|
||||
* $(D_KEYWORD void) when applied to an output range). It is because an output
|
||||
* range can support puting differently typed elements into it.
|
||||
*
|
||||
* Params:
|
||||
* R = The type to be tested.
|
||||
* E = Element type should be tested for.
|
||||
*
|
||||
* Returns: $(D_KEYWORD true) if $(D_PARAM R) is an output range for the
|
||||
* elements of the type $(D_PARAM E), $(D_KEYWORD false) otherwise.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL put).
|
||||
*/
|
||||
template isOutputRange(R, E)
|
||||
{
|
||||
@ -933,6 +923,11 @@ template isOutputRange(R, E)
|
||||
}
|
||||
else static if (isInputRange!E)
|
||||
{
|
||||
pragma(msg, "Deprecation. An input range whose element type is "
|
||||
~ "supported by the output range isn't considered itself to "
|
||||
~ "be a source for such an output range. Don't rely on this "
|
||||
~ "behavior and use tanya.algorithm.copy() to write one "
|
||||
~ "range into another one.");
|
||||
alias ET = ElementType!E;
|
||||
enum bool isOutputRange = is(typeof((R r, ET e) => put(r, e)));
|
||||
}
|
||||
@ -956,13 +951,16 @@ template isOutputRange(R, E)
|
||||
static struct R2
|
||||
{
|
||||
int value;
|
||||
|
||||
void popFront() @nogc nothrow pure @safe
|
||||
{
|
||||
}
|
||||
|
||||
ref int front() @nogc nothrow pure @safe
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
bool empty() const @nogc nothrow pure @safe
|
||||
{
|
||||
return true;
|
||||
@ -975,19 +973,18 @@ template isOutputRange(R, E)
|
||||
void popFront() @nogc nothrow pure @safe
|
||||
{
|
||||
}
|
||||
|
||||
int front() @nogc nothrow pure @safe
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool empty() const @nogc nothrow pure @safe
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
static assert(!isOutputRange!(R3, int));
|
||||
|
||||
static assert(isOutputRange!(R1, R3));
|
||||
static assert(isOutputRange!(R2, R3));
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user