Jump to page: 1 2
Thread overview
Getting the initial value of a class field in compile time.
Feb 08, 2020
realhet
Feb 09, 2020
Drug
Feb 09, 2020
realhet
Feb 09, 2020
realhet
Feb 09, 2020
Adam D. Ruppe
Feb 09, 2020
realhet
Feb 09, 2020
realhet
Feb 09, 2020
realhet
Feb 09, 2020
Paul Backus
Feb 09, 2020
realhet
February 08, 2020
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!
February 09, 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
February 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.
February 09, 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:
>> 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
February 09, 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:
>> 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.
February 09, 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)
February 09, 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:
>> 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.
February 09, 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:
>> 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;
        }}
    }
February 08, 2020
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
February 09, 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:
>> 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!

« First   ‹ Prev
1 2