www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting the initial value of a class field in compile time.

reply realhet <real_het hotmail.com> writes:
Hello,

class A{
   int i = 42;
}

Is there a way to get that 42? (Input is the class A and the name 
of the field 'i')

A.i.init returns 0, so it doesn't care about the class.

classinfo.m_init can be an option, but maybe there's a nicer way 
to do this?

Thx!
Feb 08 2020
next sibling parent reply Drug <Drug2004 bk.ru> writes:
On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote:
 Hello,

 class A{
   int i = 42;
 }

 Is there a way to get that 42? (Input is the class A and the 
 name of the field 'i')

 A.i.init returns 0, so it doesn't care about the class.

 classinfo.m_init can be an option, but maybe there's a nicer 
 way to do this?

 Thx!
Try A.init.i
Feb 08 2020
parent reply realhet <real_het hotmail.com> writes:
On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote:
 On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote:
 Hello,

 class A{
   int i = 42;
 }

 Is there a way to get that 42? (Input is the class A and the 
 name of the field 'i')

 A.i.init returns 0, so it doesn't care about the class.

 classinfo.m_init can be an option, but maybe there's a nicer 
 way to do this?

 Thx!
Try A.init.i
I tried and A.init.stringof == "void()" That generates a new question, what is void() ? It has no sizeof property. I guess it's the voidest of the voids in D :D
Feb 08 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/8/20 7:39 PM, realhet wrote:
 On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote:
 On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote:
 Hello,

 class A{
   int i = 42;
 }

 Is there a way to get that 42? (Input is the class A and the name of 
 the field 'i')

 A.i.init returns 0, so it doesn't care about the class.

 classinfo.m_init can be an option, but maybe there's a nicer way to 
 do this?

 Thx!
Try A.init.i
I tried and A.init.stringof == "void()" That generates a new question, what is void() ? It has no sizeof property. I guess it's the voidest of the voids in D :D
Looks like you wrote a function void init() inside your class. Don't do that. D has a default init property. But as an aside, A.init has a value of null. So A.init.i => segfault. The 42 lives inside the intializer, which is a void array stored in the TypeInfo. But you probably don't want to get it that way. Adam's way is technically a good way to get it. But you don't necessarily need that (and it might not be what you are looking for -- the constructor could easily change i to a different value). Problem is that typeid cannot be read at compile time. https://issues.dlang.org/show_bug.cgi?id=7147 If you could do that, you could construct a "pre-constructed" class instance, and use it as the prototype for reading the int value. -Steve
Feb 08 2020
parent realhet <real_het hotmail.com> writes:
On Sunday, 9 February 2020 at 02:25:56 UTC, Steven Schveighoffer 
wrote:
 On 2/8/20 7:39 PM, realhet wrote:
 On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote:
 On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote:
Yea, I exactly ran into that "init" problem, I will avoid that, thx!
Feb 09 2020
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote:
 classinfo.m_init can be an option, but maybe there's a nicer 
 way to do this?
eh the initializer i think is the best. you can sometimes shortcut it pragma(msg, (new A).i); which will call the ctor at ctfe and get the value. but if there isn't a default constructor that's harder. (of course at runtime you can yank it out of the init member... but ctfe will fail that i believe because of the reinterpret cast involved). i can't think of a better way right now.
Feb 08 2020
parent reply realhet <real_het hotmail.com> writes:
On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe wrote:
 On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote:
 classinfo.m_init can be an option, but maybe there's a nicer 
 way to do this?
eh the initializer i think is the best. you can sometimes shortcut it pragma(msg, (new A).i); which will call the ctor at ctfe and get the value. but if there isn't a default constructor that's harder. (of course at runtime you can yank it out of the init member... but ctfe will fail that i believe because of the reinterpret cast involved). i can't think of a better way right now.
Thank you! It works! Somehow I thought that 'new' is too much in CTFE, now I can rethink that.
Feb 08 2020
parent reply realhet <real_het hotmail.com> writes:
On Sunday, 9 February 2020 at 00:41:12 UTC, realhet wrote:
 On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe wrote:
Using what I've learned: class A{ int i=42; void init(){ // reInitialize class fields alias T = typeof(this); mixin([FieldNameTuple!T].map!(n => n~"=(new T)."~n~";").join); } } (I also like to live dangerously with string mixins :D)
Feb 08 2020
next sibling parent realhet <real_het hotmail.com> writes:
On Sunday, 9 February 2020 at 00:57:05 UTC, realhet wrote:
 On Sunday, 9 February 2020 at 00:41:12 UTC, realhet wrote:
 On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe 
 wrote:
mixin([FieldNameTuple!T].map!(n => n~"=(new T)."~n~";").join); After checking it in the asm debugger, it turned out, that it evaluates (new T) in runtime. (Silly me, because the constructor can have side effects.) So I first put the default values into an enum, and then do the assignment: foreach(n; FieldNameTuple!T){{ mixin("enum def = (new T). ; = def;".replace(" ", n)); }} And that became as fast as it can be: mov dword ptr ds:[rax+10], 2A Thanks for the help again.
Feb 08 2020
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 9 February 2020 at 00:57:05 UTC, realhet wrote:
 On Sunday, 9 February 2020 at 00:41:12 UTC, realhet wrote:
 On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe 
 wrote:
Using what I've learned: class A{ int i=42; void init(){ // reInitialize class fields alias T = typeof(this); mixin([FieldNameTuple!T].map!(n => n~"=(new T)."~n~";").join); } } (I also like to live dangerously with string mixins :D)
Tip: don't name a member function `init`, since it will conflict with the built-in `.init` property. Here's a version without string mixins, for comparison: void initialize() { static foreach (i, field; typeof(this).tupleof) {{ // force compile-time evaluation enum initValue = (new typeof(this)).tupleof[i]; field = initValue; }} }
Feb 08 2020
parent realhet <real_het hotmail.com> writes:
On Sunday, 9 February 2020 at 01:19:55 UTC, Paul Backus wrote:
 On Sunday, 9 February 2020 at 00:57:05 UTC, realhet wrote:
 On Sunday, 9 February 2020 at 00:41:12 UTC, realhet wrote:
 On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe
enum initValue = (new typeof(this)).tupleof[i];
Wow, thx! Accessing by index instead of name. Really powerful!
Feb 09 2020