Bug 19036 – .tupleof order guarantee

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P1
Component
dlang.org
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2018-06-28T05:29:19Z
Last change time
2022-07-20T12:08:06Z
Keywords
pull, spec
Assigned to
No Owner
Creator
Guillaume Lathoud

Comments

Comment #0 by gsub — 2018-06-28T05:29:19Z
Hello, currently there is no official guarantee on the order returned by .tupleof: https://dlang.org/spec/class.html#class_properties I have a use case where I'd like to serialize most fields of a class, *in their declaration order*, into a byte array. The fields are either simple arithmetic types, or dynamic arrays of arithmetic types, so I am currently doing something like this: class A { int x,y,z; int _internal_use_only; int[] arr; void packTo( ref ubyte[] result ) { result.length = 0; static foreach( i, field; A.tupleof ) // <<< HERE { static if (!__traits( identifier, field ).startsWith( "_" )) { { ubyte[] b; static if (__traits( isArithmetic, typeof( field ) )) { b ~= nativeToLittleEndian( field ); } else { foreach( v; field ) b ~= nativeToLittleEndian( v ); } result ~= b; } } } } } Since in my use case, the serialization order MUST match a spec, it is important to have a guarantee on the .tupleof order. The current implementations already seem to guarantee that order. Would it be thinkable to have the guarantee in the spec as well? Note: I found a previous discussion on this, but no issue: https://forum.dlang.org/post/[email protected] Thanks! Guillaume Lathoud
Comment #1 by doob — 2018-06-28T10:20:41Z
As a workaround, if your specification contains the names you could lookup the names using in the class using __traits(identifier, A.tupleof[i]).
Comment #2 by timosesu — 2018-06-28T14:34:51Z
I also have code depending on this property of tupleof (ordered as declared) in a struct. In my case the struct layout is handed to me and access to its properties/members has to be in the order the struct is layed out. If .tupleof were to change ever it would be a problem in this case.
Comment #3 by gsub — 2018-07-04T05:57:02Z
Thanks for the answers. In another use case there is a class hierarchy, I also need the fields of the base class, which .tupleof does not provide, so I am not sure anymore how useful the present issue would be. (I ended up using something along this line: [__traits( allMembers, MyClass)].sort() ) Maybe the spec could simply state that .tupleof does not provide any order guarantee, as already specified for __traits( allMembers, MyClass ) and __traits( derivedMembers, MyClass ).
Comment #4 by doob — 2018-07-04T10:38:20Z
(In reply to Guillaume Lathoud from comment #3) > In another use case there is a class hierarchy, I > also need the fields of the base class, which .tupleof does not provide, so > I am not sure anymore how useful the present issue would be. To get the fields of the base class you can upcast it and then use .tupleof. That is: (cast(Base) subclassObject).tupleof. You can also use some traits in Phobos to get the base class from a subclass.
Comment #5 by gsub — 2018-07-04T11:49:52Z
(In reply to Jacob Carlborg from comment #4) > To get the fields of the base class you can upcast it and then use .tupleof. > That is: (cast(Base) subclassObject).tupleof. You can also use some traits > in Phobos to get the base class from a subclass. Thanks! Now I see that the official .tupleof example *does* rely on the proper order: https://dlang.org/spec/class.html#class_properties foo.tupleof[0] = 1; // set foo.x to 1 foo.tupleof[1] = 2; // set foo.y to 2 ...so I guess this guarantee should be made explicit. That would be the topic of the issue here. One the side: is there an easy way to concatenate two expression sequences? I am thinking of something like BaseClass.tupleof ~ ChildClass.tupleof
Comment #6 by doob — 2018-07-04T18:59:25Z
(In reply to Guillaume Lathoud from comment #5) > One the side: is there an easy way to concatenate two expression sequences? > I am thinking of something like BaseClass.tupleof ~ ChildClass.tupleof You can concatenate a tuple of types using std.typecons.AliasSeq. That would be used like this: alias a = AliasSeq!(typeof(BaseClass.tupleof), typeof(ChildClass.tupleof)); It seems it's not possible to concatenate without using "typeof".
Comment #7 by gsub — 2018-07-05T04:39:38Z
(In reply to Jacob Carlborg from comment #6) > You can concatenate a tuple of types using std.typecons.AliasSeq. That would > be used like this: > > alias a = AliasSeq!(typeof(BaseClass.tupleof), typeof(ChildClass.tupleof)); > > It seems it's not possible to concatenate without using "typeof". Thanks!
Comment #8 by dlang-bot — 2022-07-20T11:20:52Z
@RazvanN7 created dlang/dlang.org pull request #3346 "Fix Issue 19036 - .tupleof order guarantee" fixing this issue: - Fix Issue 19036 - .tupleof order guarantee https://github.com/dlang/dlang.org/pull/3346
Comment #9 by dlang-bot — 2022-07-20T12:08:06Z
dlang/dlang.org pull request #3346 "Fix Issue 19036 - .tupleof order guarantee" was merged into master: - 633d7fc97321acdd71a3c01cd385d8f4166e1dca by RazvanN7: Fix Issue 19036 - .tupleof order guarantee https://github.com/dlang/dlang.org/pull/3346