Jump to page: 1 2
Thread overview
this(this) / opAssign
Jan 10, 2013
Namespace
Jan 10, 2013
monarch_dodra
Jan 10, 2013
Era Scarecrow
Jan 10, 2013
Namespace
Jan 10, 2013
monarch_dodra
Jan 11, 2013
Namespace
Jan 10, 2013
David Nadlinger
Jan 10, 2013
monarch_dodra
Jan 10, 2013
Namespace
Jan 11, 2013
monarch_dodra
Jan 11, 2013
monarch_dodra
January 10, 2013
Is it expected behaviour that this code compiles and prints:

this(this)
this(this)

?
[code]
import std.stdio;

static if (!is(typeof(writeln)))
	alias writefln writeln;

struct vec2f {
public:
	float x, y;
	
	this(this) {
		writeln("this(this)");
	}
}

void main()
{
	vec2f v1 = vec2f(0, 1);
	vec2f v2 = vec2f(2, 3);
	
	v2 = v1;
	
	vec2f v3 = v2;
}
[/code]

while this code

[code]
import std.stdio;

static if (!is(typeof(writeln)))
	alias writefln writeln;

struct vec2f {
public:
	float x, y;
	
	this(this) {
		writeln("this(this)");
	}
	
	
	ref vec2f opAssign(ref const vec2f v) {
		writeln("opAssign");
		
		this.x = v.x;
		this.y = v.y;
		
		return this;
	}
}

void main()
{
	vec2f v1 = vec2f(0, 1);
	vec2f v2 = vec2f(2, 3);
	
	v2 = v1;
	
	vec2f v3 = v2;
}
[/code]

prints:

opAssign
this(this)
?

And what should I use, this(this) or opAssign? I thougth that it is unimportant,
but that changed my mind: http://dpaste.dzfl.pl/36ce3688
January 10, 2013
On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:
> And what should I use, this(this) or opAssign? I thougth that it is unimportant,
> but that changed my mind: http://dpaste.dzfl.pl/36ce3688

The default generated opAssign will postblit the other struct over itself, then destroy it's own (old) body (if a postblit occured):

import std.stdio;

//----
struct S
{
	this(this) {
		writeln("this(this)");
	}
	~this() {
		writeln("~this");
	}
}

void main()
{
	S a, b;

	writeln("Start");
	a = b;
	writeln("Finish");
}
//----
Produces
//----
Start
this(this) //Postblit a new copy
~this      //Destroy the old body
Finish
~this
~this
//----

This is a very sweet deal: If you write a constructor (and optionally a destructor), then that's all you need for D to make things consistent. For example:

//----
import std.stdio;

struct S
{
	int* p;
	this(int i)
	{
	    p = new int;
            *p = i;
	}
	this(this)
	{
            int* p2 = new int;
	    *p2 = *p;
            p = p2;
	}
}

void main()
{
	S a = S(1);
	S b = S(2);

	writeln("Start");
	a = b;
	assert(*a.p == 2);
	assert(a.p != b.p);
	writeln("Finish");
}
//----
Here, the default generate opAssign is *not* "stupid" and will not straight up assign the pointers. After the assignments, each struct will still have their own personal payload!

Now to answer your question:
If your object is a POD, the no need for opAssign.
If your object has a constructor, then the default opAssign should remain consistent with your construcor's behavior...

...BUT: you can still implement it yourself if (and only if) you need a custom behavior. In the above example, opAssign "worked", but it did needlessly re-alocate. This is the kind of situation where writing an opAssign is worth it.
January 10, 2013
On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:
> Is it expected behaviour that this code compiles and prints:

 I think it is. Postblit 'this(this)' occurs while initializing a variable from one, rather than copying. Which you also can compare against move symantics.

 Correct me if i'm wrong.

  struct S {
    this(this) {writeln("this(this)"); }
    void opAssign(ref S s) {writeln("opAssign ref/copy");}
    void opAssign(S s) {writeln("opAssign move");}
  }



  //postblit
  S s1;
  S s2 = s1;

  //opAssign ref (copy)
  S s3;
  s3 = s1;

  //opAssign S (Move)
  S func() {return S();}
  s3 = func();


output:
  this(this)
  opAssign ref/copy
  opAssign move
January 10, 2013
On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:
> And what should I use, this(this) or opAssign? I thougth that it is unimportant,
> but that changed my mind: http://dpaste.dzfl.pl/36ce3688

BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.
January 10, 2013
On Thursday, 10 January 2013 at 23:30:35 UTC, monarch_dodra wrote:
> On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:
>> And what should I use, this(this) or opAssign? I thougth that it is unimportant,
>> but that changed my mind: http://dpaste.dzfl.pl/36ce3688
>
> BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.

It is private, sorry.
Here as public: http://dpaste.dzfl.pl/ab3c7a5c
January 10, 2013
Without a declared opAssign, this

  S s3;
  s3 = s1;

also calls the postblit. That is strange.
January 10, 2013
On Thursday, 10 January 2013 at 23:37:14 UTC, Namespace wrote:
> Without a declared opAssign, this
>
>   S s3;
>   s3 = s1;
>
> also calls the postblit. That is strange.

If there is no user declared opAssign, then opAssign is implemented in terms of postblit. It's designed that way.

This is kind of like C++'s copy and swap idiom, but built into the language.
January 10, 2013
On Thursday, 10 January 2013 at 23:37:14 UTC, Namespace wrote:
> Without a declared opAssign, this
>
>   S s3;
>   s3 = s1;
>
> also calls the postblit. That is strange.

Think of it like this: Blit means bit-by-bit copy, so a postblit is a function that is invoked on the result of every bit-by-bit copy operation. The default behavior for struct assignment is precisely to copy over the contents, so it makes sense for the postblit to be invoked in that case.

David
January 11, 2013
On Thursday, 10 January 2013 at 23:35:19 UTC, Namespace wrote:
> On Thursday, 10 January 2013 at 23:30:35 UTC, monarch_dodra wrote:
>> On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:
>>> And what should I use, this(this) or opAssign? I thougth that it is unimportant,
>>> but that changed my mind: http://dpaste.dzfl.pl/36ce3688
>>
>> BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.
>
> It is private, sorry.
> Here as public: http://dpaste.dzfl.pl/ab3c7a5c

Yeah, but if you re-arrange the tests, then you get opposite results...
http://dpaste.dzfl.pl/fork/c52f290a

Benchmarking is hard.

You could try maybe viewing the disassembly instead?
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue%2C%22colouriseAsm%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22\nstruct%20Avec2f%20{\npublic%3A\n\tfloat%20x%2C%20y%3B\n\t\n\tref%20Avec2f%20opAssign%28const%20ref%20Avec2f%20v%29%20{\n\t\tthis.x%20%3D%20v.x%3B\n\t\tthis.y%20%3D%20v.y%3B\n\t\t\n\t\treturn%20this%3B\n\t}\n}\n\nstruct%20Bvec2f%20{\npublic%3A\n\tfloat%20x%2C%20y%3B\n\t\n}\n\nstruct%20Cvec2f%20{\npublic%3A\n\tfloat%20x%2C%20y%3B\n\t\n\tthis%28this%29%20{\n\t\tthis.x%20%3D%20x%3B\n\t\tthis.y%20%3D%20y%3B\n\t}\n}\n\nvoid%20main%28%29\n{\t\n\tAvec2f%20v1%20%3D%20Avec2f%284%2C%202%29%3B\n\tAvec2f%20v2%20%3D%20Avec2f%286%2C%208%29%3B\n\tv1%20%3D%20v2%3B\n\t\n\tBvec2f%20v3%20%3D%20Bvec2f%284%2C%202%29%3B\n\tBvec2f%20v4%20%3D%20Bvec2f%286%2C%208%29%3B\n\tv3%20%3D%20v4%3B\n\n\tCvec2f%20v5%20%3D%20Cvec2f%284%2C%202%29%3B\n\tCvec2f%20v6%20%3D%20Cvec2f%286%2C%208%29%3B\n\tv5%20%3D%20v6%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%22}]}

January 11, 2013
On Friday, 11 January 2013 at 00:02:48 UTC, monarch_dodra wrote:
> On Thursday, 10 January 2013 at 23:35:19 UTC, Namespace wrote:
>> On Thursday, 10 January 2013 at 23:30:35 UTC, monarch_dodra wrote:
>>> On Thursday, 10 January 2013 at 23:03:30 UTC, Namespace wrote:
>>>> And what should I use, this(this) or opAssign? I thougth that it is unimportant,
>>>> but that changed my mind: http://dpaste.dzfl.pl/36ce3688
>>>
>>> BTW, answered to the best of my abilities, taking into account your link expired, so I don't have as much context as you tried to offer.
>>
>> It is private, sorry.
>> Here as public: http://dpaste.dzfl.pl/ab3c7a5c
>
> Yeah, but if you re-arrange the tests, then you get opposite results...
> http://dpaste.dzfl.pl/fork/c52f290a

Sorry:
http://dpaste.dzfl.pl/9ff9b84a
« First   ‹ Prev
1 2