Thread overview
minElement on array of const objects
Nov 13, 2017
Temtaime
Nov 13, 2017
Nathan S.
Nov 13, 2017
vit
November 13, 2017
Hi all,

It seems that it is not possible to use minElement on an array of const objects:

class A
{
  int val;
}

const(A) doStuff(const(A)[] v)
{
  import std.algorithm.searching : minElement;
  return v.minElement!"a.val";
}

This gets the following compiler error:

std/algorithm/searching.d(1256,28): Error: cannot implicitly convert expression (front(r)) of type const(A) to app.A
std/algorithm/searching.d(1286,35): Error: cannot implicitly convert expression (r[i]) of type const(A) to app.A
std/algorithm/searching.d(1258,36): Error: template instance std.algorithm.searching.extremum!("a.val", "a < b", const(A)[], A) error instantiating
std/algorithm/searching.d(3345,24):        instantiated from here: extremum!("a.val", "a < b", const(A)[])
source/app.d(11,11):        instantiated from here: minElement!("a.val", const(A)[])

Is there a reason why this is not allowed? Shouldn't minElement be able to return a const(A) in this situation?

Thanks,
Aurelien
November 13, 2017
On Monday, 13 November 2017 at 10:20:51 UTC, Aurelien Fredouelle wrote:
> Hi all,
>
> It seems that it is not possible to use minElement on an array of const objects:
>
> class A
> {
>   int val;
> }
>
> const(A) doStuff(const(A)[] v)
> {
>   import std.algorithm.searching : minElement;
>   return v.minElement!"a.val";
> }
>
> This gets the following compiler error:
>
> std/algorithm/searching.d(1256,28): Error: cannot implicitly convert expression (front(r)) of type const(A) to app.A
> std/algorithm/searching.d(1286,35): Error: cannot implicitly convert expression (r[i]) of type const(A) to app.A
> std/algorithm/searching.d(1258,36): Error: template instance std.algorithm.searching.extremum!("a.val", "a < b", const(A)[], A) error instantiating
> std/algorithm/searching.d(3345,24):        instantiated from here: extremum!("a.val", "a < b", const(A)[])
> source/app.d(11,11):        instantiated from here: minElement!("a.val", const(A)[])
>
> Is there a reason why this is not allowed? Shouldn't minElement be able to return a const(A) in this situation?
>
> Thanks,
> Aurelien

It should not until it uses recursion to find min element.

const(Class) res = ...;
...
return res;

Algorithm tries to assign to res variable and fails because in D const(Class) means both const object and const reference to it. So we cannot assign another reference to const(Class) variable.
November 13, 2017
>Unqual!Element seed = r.front;

>alias MapType = Unqual!(typeof(mapFun(CommonElement.init)));

This looks like a job for std.typecons.Rebindable!(const A) instead of Unqual!(const A) which is used currently. I am surprised that this is the first time anyone has run into this.

November 13, 2017
On Monday, 13 November 2017 at 12:15:26 UTC, Nathan S. wrote:
>>Unqual!Element seed = r.front;
>
>>alias MapType = Unqual!(typeof(mapFun(CommonElement.init)));
>
> This looks like a job for std.typecons.Rebindable!(const A) instead of Unqual!(const A) which is used currently. I am surprised that this is the first time anyone has run into this.

Is Unqual necessary here?:
https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1284
https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1340

And here
https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1301
https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1355
is necessary something like RebindableOrUnqual instead of Unqual:

template RebindableOrUnqual(T){
	static if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)alias RebindableOrUnqual = Rebindable!T;
	else alias RebindableOrUnqual = Unqual!T;
}
November 14, 2017
On Monday, 13 November 2017 at 14:28:27 UTC, vit wrote:
> On Monday, 13 November 2017 at 12:15:26 UTC, Nathan S. wrote:
>> [...]
>
> Is Unqual necessary here?:
> https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1284
> https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1340
>
> And here
> https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1301
> https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L1355
> is necessary something like RebindableOrUnqual instead of Unqual:
>
> template RebindableOrUnqual(T){
> 	static if (is(T == class) || is(T == interface) || isDynamicArray!T || isAssociativeArray!T)alias RebindableOrUnqual = Rebindable!T;
> 	else alias RebindableOrUnqual = Unqual!T;
> }

Thanks, I filed https://issues.dlang.org/show_bug.cgi?id=17982 to track the issue.