Search code examples
din-placephobos

In-Place Ordering of Elements


Does Phobos have some variadic algorithm to order l-value reference arguments in place? Something like

int a=3;
int b=2;
int c=1;

orderInPlace(a,b,c);

// a is now 1
// b is now 2
// c is now 3

Also a functional variant, say order(a, b, c), that returns a tuple would also be nice.

If not, I guess we should make use of std.algorithm:swap.

See also http://forum.dlang.org/thread/[email protected]#post-eweortsmcmibppmvtriw:40forum.dlang.org.


Solution

  • Adam's solution works, although it uses a temporary copy of the elements. With a small modification to std.algorithm, it's possible to write a version which sorts the elements in-place:

    import std.algorithm;
    import std.stdio;
    import std.traits;
    import std.typecons;
    
    struct SortableRef(T)
    {
        private T * _p;
        @property ref T value() { return *_p; }
        alias value this;
        void opAssign(T * value) { _p = value; }
        @disable void opAssign(SortableRef!T value);
        void proxySwap(SortableRef!T other) { swap(*_p, *other._p); }
    }
    
    template PointerTo(T) { alias T* PointerTo; }
    void orderInPlace(T...)(ref T values)
        if (!is(CommonType!(staticMap!(PointerTo, T)) == void))
    {
        alias CommonType!T E;
        SortableRef!E[values.length] references;
        foreach (i, ref v; values)
            references[i] = &v;
        references[].sort();
    }
    
    void main()
    {
        int a=3;
        int b=1;
        int c=2;
        orderInPlace(a, b, c);
        writeln([a, b, c]);
    }
    

    However, it is only practical if the values passed to orderInPlace are large, unassignable, or otherwise impractical to copy.