www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to list aggregate members in order of declaration at compile time?

reply Ivan Kazmenko <gassa mail.ru> writes:
Hi.

I want to somehow list members of a class in the order of their 
declaration.  The immediate goal is to generate a few functions, 
like the "default" constructor for structs but only with all the 
fields, or the "reader" function, but I'm interested in the 
general question as well.

I can go the hard way and wrap every declaration into something 
that will collect them and then list in the right order.  The 
problem is, the declarations won't look normal then.

The documentation for __traits (allMembers, ...), __traits 
(derivedMembers, ...) and the like [1] explicitly says that the 
order is not defined.  Still, I've looked at Atila Neves' 
Cerealed serializer library, and it does use them [2].  Does it 
mean the order is unlikely to change at this point?

The documentation for std.traits' RepresentationTypeTuple [3] 
says things are listed in topological order, which formally does 
not restrict the order for flat structures again.  And the 
underlying implementation [4] of Fields uses .tupleof class 
property which, in turn, does not list any guarantees on the 
order [5].

So I'm confused.  What is considered the right way to list 
members when I care about their linear order?

Ivan Kazmenko.

[1] https://dlang.org/spec/traits.html#derivedMembers
[2] 
https://github.com/atilaneves/cerealed/blob/master/src/cerealed/cereal.d#L467
[3] 
https://dlang.org/phobos/std_traits.html#RepresentationTypeTuple
[4] 
https://github.com/dlang/phobos/blob/10cd84a/std/traits.d#L2279
[5] https://dlang.org/spec/class.html#class_properties
Nov 10 2016
parent reply Ivan Kazmenko <gassa mail.ru> writes:
On Thursday, 10 November 2016 at 10:16:44 UTC, Ivan Kazmenko 
wrote:
 I want to somehow list members of a class in the order of their 
 declaration.
Bump. Anyone? I've met my immediate goal by other means, but the general question remains. If classes are no-go, basically, any aggregate will do if the order of declarations is reliably and reproducibly known at compile time. I'm not much into compile-time reflection, yet, but I thought that's a basic operation. Otherwise, how do people, for example, approach serializing arbitrary containers reproducibly across compiler versions - or they just don't? Well, I've seen one example (Cerealed), but the implementation details there seem to contradict the current language documentation. Ivan Kazmenko.
Nov 11 2016
parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, November 11, 2016 21:26:10 Ivan Kazmenko via Digitalmars-d-learn 
wrote:
 On Thursday, 10 November 2016 at 10:16:44 UTC, Ivan Kazmenko

 wrote:
 I want to somehow list members of a class in the order of their
 declaration.
Bump. Anyone? I've met my immediate goal by other means, but the general question remains. If classes are no-go, basically, any aggregate will do if the order of declarations is reliably and reproducibly known at compile time. I'm not much into compile-time reflection, yet, but I thought that's a basic operation. Otherwise, how do people, for example, approach serializing arbitrary containers reproducibly across compiler versions - or they just don't? Well, I've seen one example (Cerealed), but the implementation details there seem to contradict the current language documentation.
I think that the simple truth of the matter is that nothing in the spec guarantees an order for any of the operations that give a list of members of a struct or class. It's just that the implementation doesn't typically change in a way that would change the order, and folks rely on the current implementation, and it works. The correct way to get the list of member variables of a struct or class is the tupleof property. And the only order that really makes sense for it is the order of declaration. Because of what it is and what it would be used for with a struct, I think that it would be hard to argue that it would make any sense for it do anything else. For classes, it's more debatable given that the member variables rearranged within the object, but since tupleof only gives you the direct member variables and therefore doesn't give you the actual layout of the full class anyway, there really isn't any point in it giving anything but the declaration order. So, it wouldn't surprise me if Walter would agree to making it so that the spec guarantees that tupleof gives the member variables in the order that they were declared, but I would not expect such a guarantee from something like __traits(allMembers, T) which gives stuff like base class members as well as stuff like functions, where the order of declaration doesn't matter at all, and there is no obvious order that members should be listed in when you take stuff like base classes and interfaces into account. I expect that it never occurred to Walter to specify that the order of the members mattered with tupleof and that that's why the spec doesn't say. So, use tupleof, and you can create an enhancement request in bugzilla for the spec to be made clearer about it: https://issues.dlang.org - Jonathan M Davis
Nov 11 2016
parent reply Ivan Kazmenko <gassa mail.ru> writes:
On Friday, 11 November 2016 at 22:04:37 UTC, Jonathan M Davis 
wrote:
 ...

 I expect that it never occurred to Walter to specify that the 
 order of the members mattered with tupleof and that that's why 
 the spec doesn't say.

 So, use tupleof, and you can create an enhancement request in 
 bugzilla for the spec to be made clearer about it: 
 https://issues.dlang.org
Thanks for the answer! So you think the order guarantee is likely to be just granted for .tupleof if asked for. I hope to get to creating a documentation issue/PR next week, to see more reaction. Ivan Kazmenko.
Nov 11 2016
parent Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, November 11, 2016 22:26:20 Ivan Kazmenko via Digitalmars-d-learn 
wrote:
 On Friday, 11 November 2016 at 22:04:37 UTC, Jonathan M Davis

 wrote:
 ...

 I expect that it never occurred to Walter to specify that the
 order of the members mattered with tupleof and that that's why
 the spec doesn't say.

 So, use tupleof, and you can create an enhancement request in
 bugzilla for the spec to be made clearer about it:
 https://issues.dlang.org
Thanks for the answer! So you think the order guarantee is likely to be just granted for .tupleof if asked for. I hope to get to creating a documentation issue/PR next week, to see more reaction.
I suspect so, but I don't know so. Certainly, it seems conceivable that something dealing with structs and their layout would need to know the order, and having tupleof have a guaranteed order would be the easiest (though you could always look at each offset property individually and figure it out). And if you really do need to be able to do something like generate a constructor for a class based on the order of its member declarations, then you need tupleof to give the order of declaration, because the offset property won't necessarily match the order of declaration for a class. So, just provide a solid use case (if not multiple) as to why it needs to have a specific order, and you probably stand a good chance of it being added to the spec - especially since it's what the implementation does anyway, and the implementation isn't likely to change. And given that tupleof simply gives the member variables, I don't know of a good argument for why it should ever do anything other than given them in the order that they're declared. - Jonathan M Davis
Nov 11 2016