http://d.puremagic.com/issues/show_bug.cgi?id=5314



--- Comment #6 from Jonathan M Davis <jmdavisp...@gmx.com> 2010-12-06 00:21:15 
PST ---
@nfxjfg

This program shows when init, a constructor, the postblit constructor, and
opAssign are used:

import std.stdio;

struct Foo
{
    int a = 7;

    this(int a)
    {
        this.a = a;
        writefln("constructor: %s", this.a);
    }

    this(this)
    {
        writefln("postblit: %s", this.a);
    }

/+
    Foo opAssign(const ref Foo other)
    {
        this.a = other.a;
        writefln("opAssign: %s", this.a);

        return this;
    }
+/
}

void main()
{
    writefln("%s(%s): -------", __FILE__, __LINE__);
    Foo a;
    writefln("%s(%s): -------", __FILE__, __LINE__);
    auto b = Foo(6);
    writefln("%s(%s): -------", __FILE__, __LINE__);
    auto c = a;
    writefln("%s(%s): -------", __FILE__, __LINE__);
    b = c;
    writefln("%s(%s): -------", __FILE__, __LINE__);
}


The output is:

test.d(29): -------
test.d(31): -------
constructor: 6
test.d(33): -------
postblit: 7
test.d(35): -------
postblit: 7
test.d(37): -------


Notice that assignment uses the postblit constructor. If you uncomment
opAssign(), then you get this instead:

test.d(29): -------
test.d(31): -------
constructor: 6
test.d(33): -------
postblit: 7
test.d(35): -------
opAssign: 7
test.d(37): -------


Now, assignment uses opAssign(). The problem with having an immutable member
variable and a postblit constructor is that you cannot reassign that member
variable. That portion of the struct cannot be altered.

If I changed the code to

import std.stdio;

struct Foo
{
    immutable int a;

    this(int a) immutable
    {
        this.a = a;
        writefln("constructor: %s", this.a);
    }

}

void main()
{
    writefln("%s(%s): -------", __FILE__, __LINE__);
    Foo a;
    writefln("%s(%s): -------", __FILE__, __LINE__);
    auto b = Foo(6);
    writefln("%s(%s): -------", __FILE__, __LINE__);
    auto c = a;
    writefln("%s(%s): -------", __FILE__, __LINE__);
    b = c;
    writefln("%s(%s): -------", __FILE__, __LINE__);
}


then it fails to compile, giving the message

test.d(24): Error: variable test.main.b cannot modify immutable


The line b = c is illegal. Now, the line auto c = a is still legal, and you
could arguably allow a postblit constructor which didn't alter the immutable
member variables, but it does get a bit odd. You could arguably even allow for
assignment via opAssign() as long as the immutable member variable isn't
altered, but then it's probably not really copying, which would not be good.

So, I suppose that a postblit could be allowed in a struct with an immutable
member variable, but you couldn't assign to it or do a deep copy or do anything
with it that you'd normally do in a postblit constructor (though whether or not
that's a problem is debatable). But the compiler would have to be smart enough
to realize that having a postblit constructor didn't allow for assignment for
structs with immutable member variables, which may or may not be
straightforward, depending on how the compiler decides that it cannot do an
assignment to a struct with an immutable member variable.

All in all, copying structs with immutable member variables does tend to get a
bit funny. I suppose that a postblit constructor _could_ be allowed, but it is
a bit odd. Assignment certainly can't be allowed, and the postblit constructor
is assignment of a sort, but it could still work as long as it's only used when
constructing a variable. So, I don't know what the correct behavior is.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------

Reply via email to