www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - using this instead of typeof(this)

reply "Ivan Kazmenko" <gassa mail.ru> writes:
Hi!

I have recently experimented with ways to express the exact 
instantiated type of a generic struct, and found that I can in 
some cases use "this" as that type.

Here is a sample program (DMD 2.062) demonstrating various uses 
of "this" as a type:

-----
import std.stdio;

struct S
{
	int x = 1;
	int y = 0;

	void f ()
	{
		y = 1;
	}

	this (this) // postblit constructor
	{
		x = 10;
	}

	this (ref this) // not a postblit constructor
	{
		x = 100;
	}

	this (ref this, this f, typeof (this), this, ref this g)
	{
		x = 1000 + _param_0.x + f.x + _param_2.x + _param_3.x + g.x;
	}
}

void main ()
{
	S a;
	a.f ();
	S b = a;
	S c = S (a);
	S d = S (a, a, a, a, a);
	writefln ("%s %s", a.x, a.y); // 1 1
	writefln ("%s %s", b.x, b.y); // 10 1 (copied b.y = a.y)
	writefln ("%s %s", c.x, c.y); // 100 0 (did not copy)
	writefln ("%s %s", d.x, d.y); // 1032 0 (refs add 1, non-refs 
add 10)
}
-----

And so I wonder:

(1) Should I refrain from using this as a type, is it a bug?

(2) A matter of style: what is the idiomatic way to take the 
exact type of a templated struct? For example, which method 
signature to return a typeof(this) value is "better" in which way 
if all have the same effect:
-----
struct S (A, B, C)
{
...
	auto method () {...}
	S method () {...}
	S !(theA, theB, theC) method () {...}
	typeof (this) method () {...}
}
-----
Note that S, theA, theB and theC can get lengthy.


feature or an implementation-specific detail I should not ever 
use?

-----
Ivan Kazmenko.
Feb 26 2013
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Ivan Kazmenko:

 (1) Should I refrain from using this as a type, is it a bug?
Using typeof(this) is OK, and makes code more DRY.
 (2) A matter of style: what is the idiomatic way to take the 
 exact type of a templated struct? For example, which method 
 signature to return a typeof(this) value is "better" in which 
 way if all have the same effect:
 -----
 struct S (A, B, C)
 {
 ...
 	auto method () {...}
 	S method () {...}
 	S !(theA, theB, theC) method () {...}
 	typeof (this) method () {...}
 }
I think there is no common idiom here. Generally being DRY is good. typeof(this) is more explicit than auto, so I prefer that. Bye, bearophile
Feb 26 2013
prev sibling next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 26 February 2013 at 16:28:59 UTC, Ivan Kazmenko wrote:
 Hi!

 I have recently experimented with ways to express the exact 
 instantiated type of a generic struct, and found that I can in 
 some cases use "this" as that type.

 -----
 	this (ref this) // not a postblit constructor
 	this (ref this, this f, typeof (this), this, ref this g)
 -----
 Ivan Kazmenko.
There was a discussion about this recently (wasn't it with you?) and I believe the conclusion basically boiled down to "bug: accepts-wrong". Neither of those two signatures should compile. The fact that they do is a bug. If they do compile, it's undefined behavior. From there, you can't rely on anything. I think there was a bugzilla entry for it, but I'll have to look for it.
Feb 26 2013
next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Tuesday, 26 February 2013 at 16:57:50 UTC, monarch_dodra wrote:
 On Tuesday, 26 February 2013 at 16:28:59 UTC, Ivan Kazmenko 
 wrote:
 Hi!

 I have recently experimented with ways to express the exact 
 instantiated type of a generic struct, and found that I can in 
 some cases use "this" as that type.

 -----
 	this (ref this) // not a postblit constructor
 	this (ref this, this f, typeof (this), this, ref this g)
 -----
 Ivan Kazmenko.
There was a discussion about this recently (wasn't it with you?) and I believe the conclusion basically boiled down to "bug: accepts-wrong".
That would be significant change in the language, where it is?
 Neither of those two signatures should compile. The fact that 
 they do is a bug.

 If they do compile, it's undefined behavior. From there, you 
 can't rely on anything.
Certainly this is not undefined behavior because those rely on 2 language rules.
 I think there was a bugzilla entry for it, but I'll have to 
 look for it.
Feb 26 2013
prev sibling parent "Ivan Kazmenko" <gassa mail.ru> writes:
 -----
 	this (ref this) // not a postblit constructor
 	this (ref this, this f, typeof (this), this, ref this g)
 -----
There was a discussion about this recently (wasn't it with you?) and I believe the conclusion basically boiled down to "bug: accepts-wrong".
Yeah, and the curiosity on "how does one call that this(ref this) constructor?" was what triggered me to try it further here. But "this(ref this)" case was just barely touched. The thread: http://forum.dlang.org/thread/qhlsrpqajuwstvlspimf forum.dlang.org?page=2#post-op.wsh3o4nqeav7ka:40stevens-macbook-pro.local
 Neither of those two signatures should compile. The fact that 
 they do is a bug.

 If they do compile, it's undefined behavior. From there, you 
 can't rely on anything.

 I think there was a bugzilla entry for it, but I'll have to 
 look for it.
After a quick search, I didn't find anything related to this(ref this) in Bugzilla. Should I create an issue now?
Feb 26 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Tuesday, 26 February 2013 at 16:28:59 UTC, Ivan Kazmenko wrote:
 Hi!

 I have recently experimented with ways to express the exact 
 instantiated type of a generic struct, and found that I can in 
 some cases use "this" as that type.
1) D allows omitting parameter names in function definitions which are replaced by implicitly created _param_XXX. 2) This as a type in parameter list replaces type of this. What you observe is consequence of combination of this rules. The most unintuitive is that applying attribute to postblit declaration makes it a regular constructor which takes argument of that struct type.
 And so I wonder:

 (1) Should I refrain from using this as a type, is it a bug?
Better to avoid such usage.
 (2) A matter of style: what is the idiomatic way to take the 
 exact type of a templated struct? For example, which method 
 signature to return a typeof(this) value is "better" in which 
 way if all have the same effect:
 -----
 struct S (A, B, C)
 {
 ...
 	auto method () {...}
 	S method () {...}
 	S !(theA, theB, theC) method () {...}
 	typeof (this) method () {...}
 }
 -----
 Note that S, theA, theB and theC can get lengthy.
You can use template this parameter in templates and avoid in non-templates.

 language feature or an implementation-specific detail I should 
 not ever use?

 -----
 Ivan Kazmenko.
It is implementation-specific detail.
Feb 26 2013
prev sibling parent reply "Kenji Hara" <k.hara.pg gmail.com> writes:
On Tuesday, 26 February 2013 at 16:28:59 UTC, Ivan Kazmenko wrote:
 Hi!

 I have recently experimented with ways to express the exact 
 instantiated type of a generic struct, and found that I can in 
 some cases use "this" as that type.

 Here is a sample program (DMD 2.062) demonstrating various uses 
 of "this" as a type:

 -----
 import std.stdio;

 struct S
 {
 	int x = 1;
 	int y = 0;

 	void f ()
 	{
 		y = 1;
 	}

 	this (this) // postblit constructor
 	{
 		x = 10;
 	}

 	this (ref this) // not a postblit constructor
 	{
 		x = 100;
 	}

 	this (ref this, this f, typeof (this), this, ref this g)
 	{
 		x = 1000 + _param_0.x + f.x + _param_2.x + _param_3.x + g.x;
 	}
 }

 void main ()
 {
 	S a;
 	a.f ();
 	S b = a;
 	S c = S (a);
 	S d = S (a, a, a, a, a);
 	writefln ("%s %s", a.x, a.y); // 1 1
 	writefln ("%s %s", b.x, b.y); // 10 1 (copied b.y = a.y)
 	writefln ("%s %s", c.x, c.y); // 100 0 (did not copy)
 	writefln ("%s %s", d.x, d.y); // 1032 0 (refs add 1, non-refs 
 add 10)
 }
 -----

 And so I wonder:

 (1) Should I refrain from using this as a type, is it a bug?
It is definitely a bug. I cannot believe that such horrible bug is still there. If you have a time, could you please file it in bugzilla? http://d.puremagic.com/issues/
 (2) A matter of style: what is the idiomatic way to take the 
 exact type of a templated struct? For example, which method 
 signature to return a typeof(this) value is "better" in which 
 way if all have the same effect:
 -----
 struct S (A, B, C)
 {
 ...
 	auto method () {...}
 	S method () {...}
 	S !(theA, theB, theC) method () {...}
 	typeof (this) method () {...}
 }
 -----
 Note that S, theA, theB and theC can get lengthy.
Returning S, S!(...), and typeof(this) are identical. You can use them as you favorite. auto return is a little different with others. To infer return type, the method body is aggressively analyzed in compilation. If the method has mutual call with another auto return function, it will cause 'forward reference error'.

 language feature or an implementation-specific detail I should 
 not ever use?
It is implementation specific. You must not rely on that. Kenji Hara
Feb 26 2013
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 26 February 2013 at 18:22:03 UTC, Kenji Hara wrote:
 Returning S, S!(...), and typeof(this) are identical...
 Kenji Hara
Just note that if the function is const or immutable, then "typeof(this)" will be "immutable S!(...)", where as if you use an actual "S!(...)" as your return value, you'll get a mutable return. This can make a difference depending on if or if not you can strip constness by copy, for functions such as: R!T save() const; vs typeof(this) save() const; Just wanted to note it. It's a subtle difference that's often forgotten.
Feb 26 2013
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Kenji Hara:

 auto return is a little different with others. To infer return 
 type, the method body is aggressively analyzed in compilation.
So that usage of "auto" sounds like something to avoid if you want D compiler to compile quickly a lot of code. Bye, bearophile
Feb 26 2013
parent reply Ben Davis <entheh cantab.net> writes:
On 26/02/2013 18:41, bearophile wrote:
 Kenji Hara:

 auto return is a little different with others. To infer return type,
 the method body is aggressively analyzed in compilation.
So that usage of "auto" sounds like something to avoid if you want D compiler to compile quickly a lot of code.
I suspect it doesn't matter actually. The semantic analysis of the function body is going to have to happen anyway. It all depends on whether the compiler does an extra pass which it throws away the work of - which seems fairly unlikely to me (having written a couple of Java type resolvers I could have done without having to write xD).
Feb 26 2013
parent "bearophile" <bearophileHUGS lycos.com> writes:
Ben Davis:

 I suspect it doesn't matter actually.
As usual benchmarks are our friends :-) Bye, bearophile
Feb 26 2013
prev sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Tuesday, 26 February 2013 at 18:22:03 UTC, Kenji Hara wrote:
 It is definitely a bug. I cannot believe that such horrible bug 
 is still there.
 If you have a time, could you please file it in bugzilla?

 http://d.puremagic.com/issues/
 Kenji Hara
I can't believe you are not aware of that. By the way, I posted similar case to bugzilla and received WONTFIX, but I don't
Feb 26 2013
parent "Ivan Kazmenko" <gassa mail.ru> writes:
On Tuesday, 26 February 2013 at 18:46:09 UTC, Maxim Fomin wrote:
 On Tuesday, 26 February 2013 at 18:22:03 UTC, Kenji Hara wrote:
 It is definitely a bug. I cannot believe that such horrible 
 bug is still there.
 If you have a time, could you please file it in bugzilla?
I can't believe you are not aware of that. By the way, I posted similar case to bugzilla and received WONTFIX, but I don't
Thank you all for the replies! Well, it turns out there does not seem to be a universally accepted view on the topic. I've created an issue in Bugzilla nevertheless: http://d.puremagic.com/issues/show_bug.cgi?id=9597
Feb 26 2013