www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - opAssign(int) necessitates this(this) for automatic opAssign to work

reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
I've tested the following with dmd 2.037.

The compiler generated opAssign is disabled by the definition of 
opAssign(int). The compiler rejects the following assignment operation. 
(The error message is in the comment below.)

Is this by design?

When I also define post-blit, the compiler generated opAssign is 
available again and seems to work correctly. (My struct doesn't have any 
members for brevity.)

The program below compiles when this(this) is provided.

void main()
{
     S s0;
     s0 = s0;    // ERROR
}

struct S
{
     /*
       1) Define just opAssign(int); the compiler rejects the code:

        Error: function deneme.S.opAssign (int) is not callable
               using argument types (S)

        Error: cannot implicitly convert expression (s0) of
               type S to int
     */
     ref S opAssign(int)
     {
         return this;
     }

     /*
       2) Uncomment post-blit; the above error disappears and
          the compiler generated opAssign works as expected
      */
//     this(this)
//     {}
}

What is the logic behind it?

Thank you,
Ali
Dec 26 2009
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Sun, 27 Dec 2009 01:42:07 +0100, Ali =C3=87ehreli <acehreli yahoo.com=
 wrote:

 I've tested the following with dmd 2.037.

 The compiler generated opAssign is disabled by the definition of  =

 opAssign(int). The compiler rejects the following assignment operation=

 (The error message is in the comment below.)

 Is this by design?

 When I also define post-blit, the compiler generated opAssign is  =

 available again and seems to work correctly. (My struct doesn't have a=

 members for brevity.)

 The program below compiles when this(this) is provided.

 void main()
 {
      S s0;
      s0 =3D s0;    // ERROR
 }

This piece of code does post-blit, not opAssign(int). Try defining opAssign(S). That should work here. The problem is, opAssign(int) takes a right-hand parameter of type int, whereas s0 =3D s0; has a rhs of type S. -- = Simen
Dec 26 2009
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Simen kjaeraas wrote:
 On Sun, 27 Dec 2009 01:42:07 +0100, Ali Çehreli <acehreli yahoo.com> 

 I've tested the following with dmd 2.037.

 The compiler generated opAssign is disabled by the definition of
 opAssign(int). The compiler rejects the following assignment
 operation. (The error message is in the comment below.)

 Is this by design?

 When I also define post-blit, the compiler generated opAssign is
 available again and seems to work correctly. (My struct doesn't have
 any members for brevity.)

 The program below compiles when this(this) is provided.

 void main()
 {
      S s0;
      s0 = s0;    // ERROR
 }

This piece of code does post-blit, not opAssign(int).

post-blit is when an object is constructed from another one. The above has two already constructed objects on both sides. So I think it is assignment.
 Try defining opAssign(S). That should work here.

I know; but the problem is, defining opAssign(int) disables the compiler-generated opAssign(S); which is then interestingly available again, once this(this) is defined. I just wanted to know whether there is a compiler bug in this behavior. Ali
Dec 26 2009
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Simen kjaeraas wrote:
 On Sun, 27 Dec 2009 02:23:47 +0100, Ali Çehreli <acehreli yahoo.com> 

 Simen kjaeraas wrote:
  > On Sun, 27 Dec 2009 01:42:07 +0100, Ali Çehreli
 <acehreli yahoo.com> wrote:
  >
  >> I've tested the following with dmd 2.037.
  >>
  >> The compiler generated opAssign is disabled by the definition of
  >> opAssign(int). The compiler rejects the following assignment
  >> operation. (The error message is in the comment below.)
  >>
  >> Is this by design?
  >>
  >> When I also define post-blit, the compiler generated opAssign is
  >> available again and seems to work correctly. (My struct doesn't have
  >> any members for brevity.)
  >>
  >> The program below compiles when this(this) is provided.
  >>
  >> void main()
  >> {
  >>      S s0;
  >>      s0 = s0;    // ERROR
  >> }
  >
  > This piece of code does post-blit, not opAssign(int).

 post-blit is when an object is constructed from another one. The above
 has two already constructed objects on both sides. So I think it is
 assignment.

  > Try defining opAssign(S). That should work here.

 I know; but the problem is, defining opAssign(int) disables the
 compiler-generated opAssign(S); which is then interestingly available
 again, once this(this) is defined.

 I just wanted to know whether there is a compiler bug in this behavior.

 Ali

Structs being what they are (Plain Old Data),

Doesn't allowing user defined post-blit and opAssign makes them not so anymore? I think I read here some time ago that even copying is not blitting anymore, but a memberwhise copy. It would have to be, to support members of types that define their own this(this) anyway.
 opAssign(typeof(this)) is
 basically the same as this(this). In both cases, you create a copy of an
 existing struct, and thus need to .dup referenced data that should be
 unique, and whatever else your copying function needs.

Isn't assignment two operations together: destroying the old object and constructing a new one? That brings the exception safety issue. We cannot destroy the old value before ensuring that the new value will be constructed successfully. Hence, the automatic opAssign is documented to be: S* opAssign(S s) { ... bitcopy *this into tmp ... ... bitcopy s into *this ... ... call destructor on tmp ... return this; } That is from http://digitalmars.com/d/2.0/struct.html But I suspected that that defition is not exception safe; *IF copying is not blitting anymore. If an exception is thrown during copying s into *this, then we would have a half constructed object. It was then, when I was trying to see whether the automatic assignment is exception-safe, that I discovered the behavior that I asked about.
 If you define an opAssign, you've basically informed the compiler that
 this struct should only be assignable from whatever parameters opAssign
 takes.

Fine.
 If you define postblit, you've said 'this struct can be
 constructed from another instance of the same struct', meaning it's
 assignable to itself.

I fail to see that post-blit and assignment are the same. And the documentation supports my understanding. Thank you very much for your help, but because you didn't explicitly say that the documentation is wrong; I continue having my doubts. :)
 If you can't, then when would you ever do a
 postblit?

The operations post blit... ;) Ali
Dec 27 2009
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Sun, 27 Dec 2009 02:23:47 +0100, Ali =C3=87ehreli <acehreli yahoo.com=
 wrote:

 Simen kjaeraas wrote:
  > On Sun, 27 Dec 2009 01:42:07 +0100, Ali =C3=87ehreli <acehreli yaho=

 wrote:
  >
  >> I've tested the following with dmd 2.037.
  >>
  >> The compiler generated opAssign is disabled by the definition of
  >> opAssign(int). The compiler rejects the following assignment
  >> operation. (The error message is in the comment below.)
  >>
  >> Is this by design?
  >>
  >> When I also define post-blit, the compiler generated opAssign is
  >> available again and seems to work correctly. (My struct doesn't ha=

  >> any members for brevity.)
  >>
  >> The program below compiles when this(this) is provided.
  >>
  >> void main()
  >> {
  >>      S s0;
  >>      s0 =3D s0;    // ERROR
  >> }
  >
  > This piece of code does post-blit, not opAssign(int).

 post-blit is when an object is constructed from another one. The above=

 has two already constructed objects on both sides. So I think it is  =

 assignment.

  > Try defining opAssign(S). That should work here.

 I know; but the problem is, defining opAssign(int) disables the  =

 compiler-generated opAssign(S); which is then interestingly available =

 again, once this(this) is defined.

 I just wanted to know whether there is a compiler bug in this behavior=

 Ali

Structs being what they are (Plain Old Data), opAssign(typeof(this)) is basically the same as this(this). In both cases, you create a copy of an= existing struct, and thus need to .dup referenced data that should be unique, and whatever else your copying function needs. If you define an opAssign, you've basically informed the compiler that this struct should only be assignable from whatever parameters opAssign takes. If you define postblit, you've said 'this struct can be constructed from another instance of the same struct', meaning it's assignable to itself. If you can't, then when would you ever do a postblit? -- = Simen
Dec 27 2009