Skip to content

Commit

Permalink
Fix Issue 17982 - Support for const(Class) in algorithm.searching.ext…
Browse files Browse the repository at this point in the history
…remum
  • Loading branch information
wilzbach committed Apr 5, 2018
1 parent 2e105c7 commit 64d3a07
Showing 1 changed file with 85 additions and 4 deletions.
89 changes: 85 additions & 4 deletions std/algorithm/searching.d
Expand Up @@ -1268,6 +1268,16 @@ if (isInputRange!R &&
}}
}

// Rebindable doesn't work with structs
// see: https://github.com/dlang/phobos/pull/6136
private template RebindableOrUnqual(T)
{
static if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)
alias RebindableOrUnqual = Rebindable!T;
else
alias RebindableOrUnqual = Unqual!T;
}

/**
Iterates the passed range and selects the extreme element with `less`.
If the extreme element occurs multiple time, the first occurrence will be
Expand All @@ -1292,7 +1302,7 @@ in
do
{
alias Element = ElementType!Range;
Unqual!Element seed = r.front;
RebindableOrUnqual!Element seed = r.front;
r.popFront();
return extremum!(map, selector)(r, seed);
}
Expand All @@ -1309,7 +1319,7 @@ if (isInputRange!Range && !isInfinite!Range &&

alias Element = ElementType!Range;
alias CommonElement = CommonType!(Element, RangeElementType);
Unqual!CommonElement extremeElement = seedElement;
RebindableOrUnqual!CommonElement extremeElement = seedElement;


// if we only have one statement in the loop, it can be optimized a lot better
Expand Down Expand Up @@ -1467,6 +1477,26 @@ if (isInputRange!Range && !isInfinite!Range &&
assert(arr2d.extremum!"a[1]" == arr2d[1]);
}

// https://issues.dlang.org/show_bug.cgi?id=17982
@safe unittest
{
class B
{
int val;
this(int val){ this.val = val; }
}

const(B) doStuff(const(B)[] v)
{
return v.extremum!"a.val";
}
assert(doStuff([new B(1), new B(0), new B(2)]).val == 0);

const(B)[] arr = [new B(0), new B(1)];
// can't compare directly - https://issues.dlang.org/show_bug.cgi?id=1824
assert(arr.extremum!"a.val".val == 0);
}

// find
/**
Finds an individual element in an $(REF_ALTTEXT input range, isInputRange, std,range,primitives).
Expand Down Expand Up @@ -2085,8 +2115,7 @@ if (isForwardRange!R1 && isForwardRange!R2

@safe unittest
{
import std.range;
import std.stdio;
import std.range : assumeSorted;

auto r1 = assumeSorted([1, 2, 3, 3, 3, 4, 5, 6, 7, 8, 8, 8, 10]);
auto r2 = assumeSorted([3, 3, 4, 5, 6, 7, 8, 8]);
Expand Down Expand Up @@ -3453,6 +3482,38 @@ if (isInputRange!Range && !isInfinite!Range &&
assert(arr2d.minElement!"a[1]" == arr2d[1]);
}

// https://issues.dlang.org/show_bug.cgi?id=17982
@safe unittest
{
struct A
{
int val;
}

const(A)[] v = [A(0)];
assert(v.minElement!"a.val" == A(0));
}

// https://issues.dlang.org/show_bug.cgi?id=17982
@safe unittest
{
class B
{
int val;
this(int val){ this.val = val; }
}

const(B) doStuff(const(B)[] v)
{
return v.minElement!"a.val";
}
assert(doStuff([new B(1), new B(0), new B(2)]).val == 0);

const(B)[] arr = [new B(0), new B(1)];
// can't compare directly - https://issues.dlang.org/show_bug.cgi?id=1824
assert(arr.minElement!"a.val".val == 0);
}

/**
Iterates the passed range and returns the maximal element.
A custom mapping function can be passed to `map`.
Expand Down Expand Up @@ -3557,6 +3618,26 @@ if (isInputRange!Range && !isInfinite!Range &&
assert(arr2d.maxElement!"a[1]" == arr2d[1]);
}

// https://issues.dlang.org/show_bug.cgi?id=17982
@safe unittest
{
class B
{
int val;
this(int val){ this.val = val; }
}

const(B) doStuff(const(B)[] v)
{
return v.maxElement!"a.val";
}
assert(doStuff([new B(1), new B(0), new B(2)]).val == 2);

const(B)[] arr = [new B(0), new B(1)];
// can't compare directly - https://issues.dlang.org/show_bug.cgi?id=1824
assert(arr.maxElement!"a.val".val == 1);
}

// minPos
/**
Computes a subrange of `range` starting at the first occurrence of `range`'s
Expand Down

0 comments on commit 64d3a07

Please sign in to comment.