This is from a forum post.
Code:
------
void main(){
auto A = [0, 1, 2];
const B = [10, -20, 30];
schwartzSort!(i => B[i])(A); // NG
}
------
This fails because the return type of the lambda is deduced as const(int). This is silly since a copied const value type no longer needs to be const; it should be unqual.
Explicitly naming the unqual type for the delegate fixes the problem:
schwartzSort!(delegate int (i) => B[i])(A); // OK
The user shouldn't be required to do this; returning a const value type by value should be stripped of its constness, since it is not the original value being returned, but a copy.
Comment #1 by bearophile_hugs — 2013-09-03T16:35:12Z
(In reply to comment #0)
> returning a const value type by value should be stripped of
> its constness, since it is not the original value
> being returned, but a copy.
The main point of my question in D.learn was: if the array A is mutable, and the array B contains constant references (like const references to class instances), is code like this acceptable?
schwartzSort!(i => B[i])(A);
Comment #2 by hsteoh — 2013-09-03T16:56:05Z
Oh I see. I misunderstood your question, my bad. :)
Nevertheless, both issues are worth consideration. The unqual issue should be fixed, definitely.
About your actual question: I'm not so sure this is possible, although in theory, it *could* be made possible if B's elements are rebindable. So in theory, this should work:
class C { ... }
auto A = [0, 1, 2];
const B = [new C(1), new C(2), new C(3)];
schwartzSort!(i => B[i])(A);
The idea being that schwartzSort stores an array of rebindable references to the C instances, and uses that to sort A. This probably doesn't work right now because the language currently has no way to express tail-const in class references, though I'm guessing that if you use Rebindable!C, it should work.
Comment #3 by pro.mathias.lang — 2018-10-19T05:01:28Z
Nowadays this code yields:
```
/usr/local/opt/dmd/include/dlang/dmd/std/algorithm/sorting.d(2934): Error: function core.stdc.stdlib.free(void* ptr) is not callable using argument types (const(int)*)
/usr/local/opt/dmd/include/dlang/dmd/std/algorithm/sorting.d(2934): cannot pass argument cast(const(int)*)p of type const(int)* to parameter void* ptr
/usr/local/opt/dmd/include/dlang/dmd/std/algorithm/sorting.d(2952): Error: template std.algorithm.sorting.sort cannot deduce function from argument types !((a, b) => binaryFun!less(a[0], b[0]), cast(SwapStrategy)0)(ZipShortest!(cast(Flag)true, const(int)[], int[])), candidates are:
/usr/local/opt/dmd/include/dlang/dmd/std/algorithm/sorting.d(1847): std.algorithm.sorting.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable && hasAssignableElements!Range) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)
test.d(6): Error: template instance `test.main.schwartzSort!((i) => B[i], "a < b", cast(SwapStrategy)0, int[])` error instantiating
```
However, I don't think that's a DMD bug. If the implementer of the function wants to provide a more sensible interface, it's up to them, but the compiler should not magically remove one level of constness because of this.
Comment #4 by robert.schadek — 2024-12-13T18:11:12Z