In a post-blit world, with no opAssign specified, postblit
will call
for copy construction AND for assignment, thereby assignment
is always
correct.
Once postblit is swapped for a copy-constructor, absence of
opAssign
will result in invalid behaviour on assignment.
Indeed, but this was the source of the problem also, because you
could
modify immutable fields that way.
Introduction of copy constructor breaks default assignment, it
needs
to address it somehow. I think my suggestion is the only
practical
solution.
Affirmative. The DIP needs to specify how assignment is handled
if no opAssign is present but a copy ctor is present. Thanks!
The difference between a copy constructor and opAssign is how the
type checking
is performed. This leads to situations where a copy constructor
is not suitable as an assignment operator. However, if a copy
constructor is defined in a way that is correctly type checked
both as a constructor and as a normal function, then there is no
problem in using the copy constructor for assignments:
struct A
{
immutable int b;
int c;
@implicit this(ref A rhs)
{
this.c = rhs.c;
}
}
struct B
{
immutable int b;
int c;
@implicit this(ref A rhs)
{
this.b = rhs.b;
this.c = rhs.c;
}
}
void main()
{
A a, c;
A b = a;
b = c; // no problem in calling copy constructor,
immutable is
// not modified
B d, e;
B f = d;
f = d; // cannot use copy constructor because it will
modify immutable
// field B.b; for this situation you need an
opAssign to specify
// how the assignment is dealt with.
}
The problem with this approach is that some copy constructors
will also be used as assignment operators while others will not,
but with good error messages it could be handled (error on line
`f = d` : opAssign not specified and the copy constructor is not
suitable for assignments because it modifies immutable field `b`).
What are your opinions on this?