Thread overview
Avoiding Range Postblits
Feb 18, 2015
Nordlöw
Feb 18, 2015
ketmar
Feb 18, 2015
Ali Çehreli
February 18, 2015
At

https://github.com/nordlow/justd/blob/master/knet/association.d#L59

I'm constructing an array of ranges that are used further down in the function contextOf.

The expression

    nds.map!(nd => gr.dijkstraWalker(nd, ...)).array;

however triggers postblits for the range DijkstraWalker returned by the instantiator dijkstraWalker.

Can this be avoided somehow?

I'm guessing that move construction plays a key role here.

Note that I can't remove the .array as they required to be l-values because their iteration to have side-effects at the end of the function contextOf().
February 18, 2015
On Wed, 18 Feb 2015 22:51:17 +0000, Nordlöw wrote:

> Can this be avoided somehow?

i don't think so. you can use heap-allocated structs, of course, or maybe `RefCounted!` can do the trick, but i not tried it.

February 18, 2015
On 02/18/2015 02:51 PM, "Nordlöw" wrote:

> I'm guessing that move construction plays a key role here.

move() does avoid the post-blit but you get many destructions in return:

import std.stdio;
import std.algorithm;
import core.memory;

struct Graph
{}

struct DW
{
    int i;

    this(int i)
    {
        writefln(" this() for %s", i);
        this.i = i;
    }

    ~this()
    {
        writefln("~this() for %s", i);
    }

    this(this)
    {
        writefln("this(this) for %s", i);
        assert(false, "Oops");
    }
}

DW dw(Graph gr, int i)
{
    return DW(i);
}

void main()
{
    auto gr = Graph();
    auto arr = [ 1, 2, 3 ];
    auto dws = new DW[arr.length];

    foreach (i, el; arr) {
        auto source = gr.dw(el);
        move(source, dws[i]);
    }

    writeln(dws);
}

The output:

 this() for 1
~this() for 0
~this() for 0
 this() for 2
~this() for 0
~this() for 0
 this() for 3
~this() for 0
~this() for 0
[DW(1), DW(2), DW(3)]
~this() for 3
~this() for 2
~this() for 1

Ali