mirror of
https://github.com/dlang/phobos.git
synced 2025-05-07 19:49:36 +03:00
fix Issue 5939 - Cannot copy std.algorithm.map
Move out Voldemort types to modle level.
This commit is contained in:
parent
0a5c88daf3
commit
cedddcd23e
2 changed files with 298 additions and 301 deletions
597
std/algorithm.d
597
std/algorithm.d
|
@ -377,90 +377,90 @@ template map(fun...) if (fun.length >= 1)
|
||||||
alias unaryFun!fun _fun;
|
alias unaryFun!fun _fun;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Result
|
return MapResult!(_fun, Range)(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct MapResult(alias fun, Range)
|
||||||
|
{
|
||||||
|
alias Unqual!Range R;
|
||||||
|
//alias typeof(fun(.ElementType!R.init)) ElementType;
|
||||||
|
R _input;
|
||||||
|
|
||||||
|
static if (isBidirectionalRange!R)
|
||||||
|
{
|
||||||
|
@property auto ref back()
|
||||||
{
|
{
|
||||||
alias Unqual!Range R;
|
return fun(_input.back);
|
||||||
alias typeof(_fun(.ElementType!R.init)) ElementType;
|
|
||||||
R _input;
|
|
||||||
|
|
||||||
static if (isBidirectionalRange!R)
|
|
||||||
{
|
|
||||||
@property auto ref back()
|
|
||||||
{
|
|
||||||
return _fun(_input.back);
|
|
||||||
}
|
|
||||||
|
|
||||||
void popBack()
|
|
||||||
{
|
|
||||||
_input.popBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this(R input)
|
|
||||||
{
|
|
||||||
_input = input;
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (isInfinite!R)
|
|
||||||
{
|
|
||||||
// Propagate infinite-ness.
|
|
||||||
enum bool empty = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@property bool empty()
|
|
||||||
{
|
|
||||||
return _input.empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront()
|
|
||||||
{
|
|
||||||
_input.popFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
@property auto ref front()
|
|
||||||
{
|
|
||||||
return _fun(_input.front);
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (isRandomAccessRange!R)
|
|
||||||
{
|
|
||||||
auto ref opIndex(size_t index)
|
|
||||||
{
|
|
||||||
return _fun(_input[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (hasLength!R || isSomeString!R)
|
|
||||||
{
|
|
||||||
@property auto length()
|
|
||||||
{
|
|
||||||
return _input.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
alias length opDollar;
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (hasSlicing!R)
|
|
||||||
{
|
|
||||||
auto opSlice(size_t lowerBound, size_t upperBound)
|
|
||||||
{
|
|
||||||
return typeof(this)(_input[lowerBound..upperBound]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (isForwardRange!R)
|
|
||||||
@property auto save()
|
|
||||||
{
|
|
||||||
auto result = this;
|
|
||||||
result._input = result._input.save;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result(r);
|
void popBack()
|
||||||
|
{
|
||||||
|
_input.popBack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this(R input)
|
||||||
|
{
|
||||||
|
_input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (isInfinite!R)
|
||||||
|
{
|
||||||
|
// Propagate infinite-ness.
|
||||||
|
enum bool empty = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@property bool empty()
|
||||||
|
{
|
||||||
|
return _input.empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront()
|
||||||
|
{
|
||||||
|
_input.popFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
@property auto ref front()
|
||||||
|
{
|
||||||
|
return fun(_input.front);
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (isRandomAccessRange!R)
|
||||||
|
{
|
||||||
|
auto ref opIndex(size_t index)
|
||||||
|
{
|
||||||
|
return fun(_input[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (hasLength!R || isSomeString!R)
|
||||||
|
{
|
||||||
|
@property auto length()
|
||||||
|
{
|
||||||
|
return _input.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
alias length opDollar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (hasSlicing!R)
|
||||||
|
{
|
||||||
|
auto opSlice(size_t lowerBound, size_t upperBound)
|
||||||
|
{
|
||||||
|
return typeof(this)(_input[lowerBound..upperBound]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (isForwardRange!R)
|
||||||
|
@property auto save()
|
||||||
|
{
|
||||||
|
auto result = this;
|
||||||
|
result._input = result._input.save;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
@ -1092,54 +1092,54 @@ template filter(alias pred) if (is(typeof(unaryFun!pred)))
|
||||||
{
|
{
|
||||||
auto filter(Range)(Range rs) if (isInputRange!(Unqual!Range))
|
auto filter(Range)(Range rs) if (isInputRange!(Unqual!Range))
|
||||||
{
|
{
|
||||||
struct FilteredRange
|
return FilterResult!(unaryFun!pred, Range)(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct FilterResult(alias pred, Range)
|
||||||
|
{
|
||||||
|
alias Unqual!Range R;
|
||||||
|
R _input;
|
||||||
|
|
||||||
|
this(R r)
|
||||||
|
{
|
||||||
|
_input = r;
|
||||||
|
while (!_input.empty && !pred(_input.front))
|
||||||
{
|
{
|
||||||
alias Unqual!Range R;
|
_input.popFront();
|
||||||
R _input;
|
|
||||||
|
|
||||||
this(R r)
|
|
||||||
{
|
|
||||||
_input = r;
|
|
||||||
while (!_input.empty && !unaryFun!pred(_input.front))
|
|
||||||
{
|
|
||||||
_input.popFront();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto opSlice() { return this; }
|
|
||||||
|
|
||||||
static if (isInfinite!Range)
|
|
||||||
{
|
|
||||||
enum bool empty = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@property bool empty() { return _input.empty; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront()
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
_input.popFront();
|
|
||||||
} while (!_input.empty && !unaryFun!pred(_input.front));
|
|
||||||
}
|
|
||||||
|
|
||||||
@property auto ref front()
|
|
||||||
{
|
|
||||||
return _input.front;
|
|
||||||
}
|
|
||||||
|
|
||||||
static if(isForwardRange!R)
|
|
||||||
{
|
|
||||||
@property auto save()
|
|
||||||
{
|
|
||||||
return typeof(this)(_input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return FilteredRange(rs);
|
auto opSlice() { return this; }
|
||||||
|
|
||||||
|
static if (isInfinite!Range)
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@property bool empty() { return _input.empty; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
_input.popFront();
|
||||||
|
} while (!_input.empty && !pred(_input.front));
|
||||||
|
}
|
||||||
|
|
||||||
|
@property auto ref front()
|
||||||
|
{
|
||||||
|
return _input.front;
|
||||||
|
}
|
||||||
|
|
||||||
|
static if(isForwardRange!R)
|
||||||
|
{
|
||||||
|
@property auto save()
|
||||||
|
{
|
||||||
|
return typeof(this)(_input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,56 +1256,53 @@ template filterBidirectional(alias pred)
|
||||||
{
|
{
|
||||||
auto filterBidirectional(Range)(Range r) if (isBidirectionalRange!(Unqual!Range))
|
auto filterBidirectional(Range)(Range r) if (isBidirectionalRange!(Unqual!Range))
|
||||||
{
|
{
|
||||||
struct Result
|
return FilterBidiResult!(unaryFun!pred, Range)(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct FilterBidiResult(alias pred, Range)
|
||||||
|
{
|
||||||
|
alias Unqual!Range R;
|
||||||
|
R _input;
|
||||||
|
|
||||||
|
this(R r)
|
||||||
|
{
|
||||||
|
_input = r;
|
||||||
|
while (!_input.empty && !pred(_input.front)) _input.popFront();
|
||||||
|
while (!_input.empty && !pred(_input.back)) _input.popBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@property bool empty() { return _input.empty; }
|
||||||
|
|
||||||
|
void popFront()
|
||||||
|
{
|
||||||
|
do
|
||||||
{
|
{
|
||||||
alias Unqual!Range R;
|
_input.popFront();
|
||||||
alias unaryFun!pred predFun;
|
} while (!_input.empty && !pred(_input.front));
|
||||||
R _input;
|
}
|
||||||
|
|
||||||
this(R r)
|
@property auto ref front()
|
||||||
{
|
{
|
||||||
_input = r;
|
return _input.front;
|
||||||
while (!_input.empty && !predFun(_input.front)) _input.popFront();
|
}
|
||||||
while (!_input.empty && !predFun(_input.back)) _input.popBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
@property bool empty() { return _input.empty; }
|
void popBack()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
_input.popBack();
|
||||||
|
} while (!_input.empty && !pred(_input.back));
|
||||||
|
}
|
||||||
|
|
||||||
void popFront()
|
@property auto ref back()
|
||||||
{
|
{
|
||||||
do
|
return _input.back;
|
||||||
{
|
}
|
||||||
_input.popFront();
|
|
||||||
} while (!_input.empty && !predFun(_input.front));
|
|
||||||
}
|
|
||||||
|
|
||||||
@property auto ref front()
|
@property auto save()
|
||||||
{
|
{
|
||||||
return _input.front;
|
return typeof(this)(_input.save);
|
||||||
}
|
|
||||||
|
|
||||||
void popBack()
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
_input.popBack();
|
|
||||||
} while (!_input.empty && !predFun(_input.back));
|
|
||||||
}
|
|
||||||
|
|
||||||
@property auto ref back()
|
|
||||||
{
|
|
||||||
return _input.back;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property auto save()
|
|
||||||
{
|
|
||||||
Result result;
|
|
||||||
result._input = _input.save;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result(r);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2211,95 +2208,95 @@ unittest
|
||||||
auto splitter(alias isTerminator, Range)(Range input)
|
auto splitter(alias isTerminator, Range)(Range input)
|
||||||
if (is(typeof(unaryFun!(isTerminator)(ElementType!(Range).init))))
|
if (is(typeof(unaryFun!(isTerminator)(ElementType!(Range).init))))
|
||||||
{
|
{
|
||||||
struct Result
|
return SplitterResult!(unaryFun!isTerminator, Range)(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct SplitterResult(alias isTerminator, Range)
|
||||||
|
{
|
||||||
|
private Range _input;
|
||||||
|
private size_t _end;
|
||||||
|
|
||||||
|
this(Range input)
|
||||||
{
|
{
|
||||||
private Range _input;
|
_input = input;
|
||||||
private size_t _end;
|
if (_input.empty)
|
||||||
private alias unaryFun!isTerminator _isTerminator;
|
|
||||||
|
|
||||||
this(Range input)
|
|
||||||
{
|
{
|
||||||
_input = input;
|
_end = _end.max;
|
||||||
if (_input.empty)
|
|
||||||
{
|
|
||||||
_end = _end.max;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Chase first terminator
|
|
||||||
while (_end < _input.length && !_isTerminator(_input[_end]))
|
|
||||||
{
|
|
||||||
++_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (isInfinite!Range)
|
|
||||||
{
|
|
||||||
enum bool empty = false; // Propagate infiniteness.
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@property bool empty()
|
// Chase first terminator
|
||||||
{
|
while (_end < _input.length && !isTerminator(_input[_end]))
|
||||||
return _end == _end.max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@property Range front()
|
|
||||||
{
|
|
||||||
assert(!empty);
|
|
||||||
return _input[0 .. _end];
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront()
|
|
||||||
{
|
|
||||||
assert(!empty);
|
|
||||||
if (_input.empty)
|
|
||||||
{
|
|
||||||
_end = _end.max;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Skip over existing word
|
|
||||||
_input = _input[_end .. _input.length];
|
|
||||||
// Skip terminator
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (_input.empty)
|
|
||||||
{
|
|
||||||
// Nothing following the terminator - done
|
|
||||||
_end = _end.max;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!_isTerminator(_input.front))
|
|
||||||
{
|
|
||||||
// Found a legit next field
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_input.popFront();
|
|
||||||
}
|
|
||||||
assert(!_input.empty && !_isTerminator(_input.front));
|
|
||||||
// Prepare _end
|
|
||||||
_end = 1;
|
|
||||||
while (_end < _input.length && !_isTerminator(_input[_end]))
|
|
||||||
{
|
{
|
||||||
++_end;
|
++_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static if(isForwardRange!Range)
|
static if (isInfinite!Range)
|
||||||
|
{
|
||||||
|
enum bool empty = false; // Propagate infiniteness.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@property bool empty()
|
||||||
{
|
{
|
||||||
@property typeof(this) save()
|
return _end == _end.max;
|
||||||
{
|
|
||||||
auto ret = this;
|
|
||||||
ret._input = _input.save;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result(input);
|
@property Range front()
|
||||||
|
{
|
||||||
|
assert(!empty);
|
||||||
|
return _input[0 .. _end];
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront()
|
||||||
|
{
|
||||||
|
assert(!empty);
|
||||||
|
if (_input.empty)
|
||||||
|
{
|
||||||
|
_end = _end.max;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Skip over existing word
|
||||||
|
_input = _input[_end .. _input.length];
|
||||||
|
// Skip terminator
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (_input.empty)
|
||||||
|
{
|
||||||
|
// Nothing following the terminator - done
|
||||||
|
_end = _end.max;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isTerminator(_input.front))
|
||||||
|
{
|
||||||
|
// Found a legit next field
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_input.popFront();
|
||||||
|
}
|
||||||
|
assert(!_input.empty && !isTerminator(_input.front));
|
||||||
|
// Prepare _end
|
||||||
|
_end = 1;
|
||||||
|
while (_end < _input.length && !isTerminator(_input[_end]))
|
||||||
|
{
|
||||||
|
++_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static if(isForwardRange!Range)
|
||||||
|
{
|
||||||
|
@property typeof(this) save()
|
||||||
|
{
|
||||||
|
auto ret = this;
|
||||||
|
ret._input = _input.save;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto L = iota(1L, 10L);
|
auto L = iota(1L, 10L);
|
||||||
|
@ -2639,65 +2636,65 @@ assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][]));
|
||||||
auto uniq(alias pred = "a == b", Range)(Range r)
|
auto uniq(alias pred = "a == b", Range)(Range r)
|
||||||
if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool))
|
if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool))
|
||||||
{
|
{
|
||||||
struct Result
|
return UniqResult!(binaryFun!pred, Range)(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct UniqResult(alias pred, Range)
|
||||||
|
{
|
||||||
|
Range _input;
|
||||||
|
|
||||||
|
this(Range input)
|
||||||
{
|
{
|
||||||
Range _input;
|
_input = input;
|
||||||
|
|
||||||
this(Range input)
|
|
||||||
{
|
|
||||||
_input = input;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto opSlice()
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void popFront()
|
|
||||||
{
|
|
||||||
auto last = _input.front;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
_input.popFront();
|
|
||||||
}
|
|
||||||
while (!_input.empty && binaryFun!(pred)(last, _input.front));
|
|
||||||
}
|
|
||||||
|
|
||||||
@property ElementType!Range front() { return _input.front; }
|
|
||||||
|
|
||||||
static if (isBidirectionalRange!Range)
|
|
||||||
{
|
|
||||||
void popBack()
|
|
||||||
{
|
|
||||||
auto last = _input.back;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
_input.popBack();
|
|
||||||
}
|
|
||||||
while (!_input.empty && binaryFun!pred(last, _input.back));
|
|
||||||
}
|
|
||||||
|
|
||||||
@property ElementType!Range back() { return _input.back; }
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (isInfinite!Range)
|
|
||||||
{
|
|
||||||
enum bool empty = false; // Propagate infiniteness.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@property bool empty() { return _input.empty; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static if (isForwardRange!Range) {
|
|
||||||
@property typeof(this) save() {
|
|
||||||
return typeof(this)(_input.save);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result(r);
|
auto opSlice()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront()
|
||||||
|
{
|
||||||
|
auto last = _input.front;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
_input.popFront();
|
||||||
|
}
|
||||||
|
while (!_input.empty && pred(last, _input.front));
|
||||||
|
}
|
||||||
|
|
||||||
|
@property ElementType!Range front() { return _input.front; }
|
||||||
|
|
||||||
|
static if (isBidirectionalRange!Range)
|
||||||
|
{
|
||||||
|
void popBack()
|
||||||
|
{
|
||||||
|
auto last = _input.back;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
_input.popBack();
|
||||||
|
}
|
||||||
|
while (!_input.empty && pred(last, _input.back));
|
||||||
|
}
|
||||||
|
|
||||||
|
@property ElementType!Range back() { return _input.back; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (isInfinite!Range)
|
||||||
|
{
|
||||||
|
enum bool empty = false; // Propagate infiniteness.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@property bool empty() { return _input.empty; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static if (isForwardRange!Range) {
|
||||||
|
@property typeof(this) save() {
|
||||||
|
return typeof(this)(_input.save);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
|
|
@ -757,7 +757,7 @@ Example:
|
||||||
@trusted int sub(int a, int b) {return a-b;}
|
@trusted int sub(int a, int b) {return a-b;}
|
||||||
@system int mul(int a, int b) {return a*b;}
|
@system int mul(int a, int b) {return a*b;}
|
||||||
|
|
||||||
htatic assert( isSafe!add);
|
static assert( isSafe!add);
|
||||||
static assert( isSafe!sub);
|
static assert( isSafe!sub);
|
||||||
static assert(!isSafe!mul);
|
static assert(!isSafe!mul);
|
||||||
--------------------
|
--------------------
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue