On Wednesday, 23 January 2013 at 12:07:48 UTC, monarch_dodra wrote:
On Wednesday, 23 January 2013 at 11:03:45 UTC, Minas Mina wrote:
Why is it required to have the .init property? Where is it useful and why was this decision made?

.init is very useful in the sense that it represents the raw object, *statically*.

This is useful for declaring statics.

It also makes constructors straightforward, in a simple 2 pass scheme (copy T.init, then run constructor).

More importantly, the T.init state is also the one you are supposed to have post destruction (Or at least, calling a destructor on T.init is supposed to be safe). This allows for some *very* efficient and built-in move semantics:

To move a into b, simply destroy b, memcopy a into b, memcopy T.init over a.

Notice how massively simpler this is compared to C++'s explicit Rvalue references? I *dare* you to try doing that with C++.

"DEFAULT" constructor breaks this entire scheme, as it implies that T.init is not an object's natural state. It jeopardizes a static destructible state.

The problem is that this overlaps with having an "explicit constructor that takes no arguments". This is particularly problematic for objects that have pointers to payloads that represent "shallow" objects. AA's is a prime example of this:

//----
    void insert5(int[int] i)
    {
        i[5] = 5;
    }

    int[int] a;           //Un-initialized T.init state
    int[int] b = [1 : 1]; //initialized
    int[int] c = [1 : 1]; c.remove(1); //Empty but initialized
    insert5(a);
    insert5(b);
    insert5(c);
    assert(a is null);           //Oh no!
    assert(b == [1 : 1, 5 : 5]); //5 correctly appended
    assert(c == [5 : 5]);        //5 correctly copied
//----

In this example, I had to jump through loops to initialize c.

Really good explanation. Thank you. So @disabled default constructor was just a "side effect" of doing those that you described.

Reply via email to