digitalmars.D.learn - Template this parameter in constructor
- Vlad Leberstein (43/43) Feb 21 2016 Hi! I'm struggling to use "Template This Parameters" feature(as
- Steven Schveighoffer (17/57) Feb 21 2016 This isn't a bug. Here is what happens.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (8/10) Feb 21 2016 I've just checked: Adding a C4 to the interitance chain (and
- Vlad Leberstein (40/56) Feb 26 2016 Many thanks to both of you, Steven and Ali! Now this makes much
Hi! I'm struggling to use "Template This Parameters" feature(as described in https://dlang.org/spec/template.html#TemplateThisParameter) in class constructor. But it's usage isn't documented very clearly and I'm not even sure if it's supposed to work this way. Consider the following example: class C1 { this(this This)() { pragma(msg, "C1 constructor: "~__traits(identifier, This)); } } class C2 : C1 { this(this This)() { pragma(msg, "C2 constructor: "~__traits(identifier, This)); super(); } } class C3 : C2 { this(this This)() { pragma(msg, "C3 constructor: "~__traits(identifier, This)); super(); } } int main(string[] args) { auto test = new C3(); return 0; } The output is: C3 constructor: C3 C2 constructor: C3 C1 constructor: C2 As you can see this works but doesn't produce the desired behavior - we can't get static type of the C3 class in C1 constructor. I suspect that it's somehow related to the fact that templated functions can't be virtual. And here comes the question: Is this a bug or the way things are supposed to work(and hence should be documented)? It would be immensely helpful to have such kind of compile-time information(for usecases vastly similar to what's described in http://forum.dlang.org/thread/mailman.1403.1361371073.22503.digitalm rs-d puremagic.com) cause currently I'm using some kind of CRTP pattern with multilevel inheritance support instead and it feels very very very weird in D world. Thanks in advance!
Feb 21 2016
On 2/21/16 11:48 AM, Vlad Leberstein wrote:Hi! I'm struggling to use "Template This Parameters" feature(as described in https://dlang.org/spec/template.html#TemplateThisParameter) in class constructor. But it's usage isn't documented very clearly and I'm not even sure if it's supposed to work this way. Consider the following example: class C1 { this(this This)() { pragma(msg, "C1 constructor: "~__traits(identifier, This)); } } class C2 : C1 { this(this This)() { pragma(msg, "C2 constructor: "~__traits(identifier, This)); super(); } } class C3 : C2 { this(this This)() { pragma(msg, "C3 constructor: "~__traits(identifier, This)); super(); } } int main(string[] args) { auto test = new C3(); return 0; } The output is: C3 constructor: C3 C2 constructor: C3 C1 constructor: C2 As you can see this works but doesn't produce the desired behavior - we can't get static type of the C3 class in C1 constructor. I suspect that it's somehow related to the fact that templated functions can't be virtual. And here comes the question: Is this a bug or the way things are supposed to work(and hence should be documented)?This isn't a bug. Here is what happens. 1. template this is assigned the compile-time type of the object *when the function is called*. 2. A base class constructor is called from the next derived constructor. So C2's constructor is called from C3's, and C1's constructor is called from C2's. So it follows that the template this type will be the next derived constructor (or the type itself if that is the most derived type), because that's the compile-time type the object's ctor is called with.It would be immensely helpful to have such kind of compile-time information(for usecases vastly similar to what's described in http://forum.dlang.org/thread/mailman.1403.1361371073.22503.digitalmars-d puremagic.com) cause currently I'm using some kind of CRTP pattern with multilevel inheritance support instead and it feels very very very weird in D world.I think you may be able to do something like this: this(T = typeof(this))() { super!T(); } But I'm not sure if it works. -Steve
Feb 21 2016
On 02/21/2016 01:48 PM, Steven Schveighoffer wrote:So it follows that the template this type will be the next derived constructor (or the type itself if that is the most derived type),I've just checked: Adding a C4 to the interitance chain (and constructing a C4) confirms that to be the case: C4 constructor: C4 C3 constructor: C4 C2 constructor: C3 C1 constructor: C2 Ali
Feb 21 2016
On Sunday, 21 February 2016 at 21:48:21 UTC, Steven Schveighoffer wrote:This isn't a bug. Here is what happens. 1. template this is assigned the compile-time type of the object *when the function is called*. 2. A base class constructor is called from the next derived constructor. So C2's constructor is called from C3's, and C1's constructor is called from C2's. So it follows that the template this type will be the next derived constructor (or the type itself if that is the most derived type), because that's the compile-time type the object's ctor is called with.Many thanks to both of you, Steven and Ali! Now this makes much more sense!I think you may be able to do something like this: this(T = typeof(this))() { super!T(); } But I'm not sure if it works.class C1 { this(This = typeof(this))() { pragma(msg, "C1 constructor: "~__traits(identifier, This)); } } class C2 : C1 { this(This = typeof(this))() { pragma(msg, "C2 constructor: "~__traits(identifier, This)); super.__ctor!This(); } } class C3 : C2 { this(This = typeof(this))() { pragma(msg, "C3 constructor: "~__traits(identifier, This)); super.__ctor!This(); } } int main(string[] args) { auto test = new C3(); return 0; } Compilation output: C3 constructor: C3 C2 constructor: C3 C1 constructor: C3 C1 constructor: C1 C2 constructor: C2 C1 constructor: C2 A little bit modified solution compiles but doesn't work as expected(tested on dmd 2.070) and produces some quite strange results and I really don't get why. But now it's not critical for me cause I managed to solve my initial problem with major refactoring. Many thanks again!
Feb 26 2016