digitalmars.D.learn - Getting the initial value of a class field in compile time.
- realhet (10/10) Feb 08 2020 Hello,
- Drug (2/12) Feb 08 2020 Try A.init.i
- realhet (5/22) Feb 08 2020 I tried and A.init.stringof == "void()"
- Steven Schveighoffer (14/39) Feb 08 2020 Looks like you wrote a function void init() inside your class.
- realhet (4/7) Feb 09 2020 Yea, I exactly ran into that "init" problem, I will avoid that,
- Adam D. Ruppe (9/11) Feb 08 2020 eh the initializer i think is the best. you can sometimes
- realhet (4/15) Feb 08 2020 Thank you! It works!
- realhet (10/11) Feb 08 2020 Using what I've learned:
- realhet (13/16) Feb 08 2020 mixin([FieldNameTuple!T].map!(n => n~"=(new T)."~n~";").join);
- Paul Backus (11/24) Feb 08 2020 Tip: don't name a member function `init`, since it will conflict
- realhet (2/6) Feb 09 2020 Wow, thx! Accessing by index instead of name. Really powerful!
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
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
On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote:On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote: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 :DHello, 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
On 2/8/20 7:39 PM, realhet wrote:On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote: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. -SteveOn Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote: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 :DHello, 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
On Sunday, 9 February 2020 at 02:25:56 UTC, Steven Schveighoffer wrote:On 2/8/20 7:39 PM, realhet wrote:Yea, I exactly ran into that "init" problem, I will avoid that, thx!On Sunday, 9 February 2020 at 00:15:47 UTC, Drug wrote:On Saturday, 8 February 2020 at 23:37:56 UTC, realhet wrote:
Feb 09 2020
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
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:Thank you! It works! Somehow I thought that 'new' is too much in CTFE, now I can rethink that.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
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
On Sunday, 9 February 2020 at 00:57:05 UTC, realhet wrote:On Sunday, 9 February 2020 at 00:41:12 UTC, realhet 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.On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe wrote:
Feb 08 2020
On Sunday, 9 February 2020 at 00:57:05 UTC, realhet wrote:On Sunday, 9 February 2020 at 00:41:12 UTC, realhet wrote: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; }} }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
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:Wow, thx! Accessing by index instead of name. Really powerful!On Sunday, 9 February 2020 at 00:41:12 UTC, realhet wrote:enum initValue = (new typeof(this)).tupleof[i];On Sunday, 9 February 2020 at 00:27:21 UTC, Adam D. Ruppe
Feb 09 2020