[OT][RFC] standardized compile-time reflection

Dear members of the Boost community, (Sorry for being slightly off-topic here) In the last couple or years I've been working on the design and implementation of portable reflection in C++. I've written several reflection libraries (that are hopefuly gradually improving). For the latest incarnation see the Mirror reflection utilities written in C++11: http://kifri.fri.uniza.sk/~chochlik/mirror-lib/html/ Recently I've learned that the Standardization Committee has issued a call for proposals for additions to the standard to the wider community, so I've decided to write down my own ideas on how compile-time reflection should look like in C++. Afterwards I discussed it with several people including Dean Michael Berris, who is the co-author of n3340 "Rich pointers" and is also interested in adding run-time (and static) reflection to C++. We've decided that we merge the ideas from my paper into his proposal (which has not happened yet and will probably take a while). However, n3340 deals with more than just static reflection, so I would like to start a discussion and ask the members of the Boost community for their opinions about the compile-time-specific parts that are described in the following paper, before writing the final proposal: http://kifri.fri.uniza.sk/~chochlik/jtc1_sc22_wg21/std_cpp_refl.pdf It is a bit lengthy so you can skip sections 1., 2. and probably also section 3., if you are knowledgeable about the domain. The most important parts are: the whole section 4. "Technical specification" and also 5., 6. and 7. Section 7. "Unresolved issues" lists several important things that need to be worked out and 3. has some rationale for the design decisions. Note that the paper has the basic structure of a standard proposal, but is not written in standardese nor is it "polished" (since it will be merged into another paper and probably re-worded). It is my first attempt at a standard proposal and I'm not a member of the Committee so please bear with me :-). Dean and I have also independently decided to write proof-of-concept implementations - compiler extensions for clang and gcc respectivelly. The sources for the gcc plugin are hosted here: https://github.com/matus-chochlik/std_cpp_refl It's in a very early stage, but if someone has some tips or hints they'll be welcome. Thanks in advance for any (negative or positive) feedback. Best regards, Matus Chochlik

Hi, On Fri, Apr 20, 2012 at 6:11 PM, Matus Chochlik <chochlik@gmail.com> wrote: [...]
Thanks in advance for any (negative or positive) feedback.
I am interested a lot in introspection in C++. I have been using another approach (and extended) boost.reflect. I'd like to participate in the effort. The document is rather lengthy though and I am not done reading (I've been away the past few days). Here are a few comments though: - Globally you start with the complex stuff. Yes what you did is very powerful and complete, but please consider the user point of view first. I am a user for reflection data and here is what I'd like to see when I am thinking about introspection in C++: #pragma reflect // generate metadata for the next language element sturct Reflected { int a; string b; double c; }; vector<Reflected> myData; CsvWriteHeader<Reflected>(myFile); for (auto& entry: myData) CsvWriteLine(myFile, entry); All the meta programming is very clever but has (IMHO) a smaller target audience, it's the mean, not the purpose. I believe you should start with the purpose then explain how you did it. So as a first piece of advice, I'd show how to reflect a POD (only data members) then a class (methods, static members) then a template and a template instance (if that is possible didn't check yet). - I think you are neglecting the aspect on how the user can choose the types that are going to be reflected. I believe not all types should have their metadata generated, at least to save on compile time on large projects. The way I did it in my preprocessor was using a pragma directive but it was much simpler than Mirror since it was only intended for classes. There migth be other ways, though, but it should be made more explicit. If reflection makes it into the standard, there shouldn't be any tools to generate the metadata besides the compiler. For the standard library, I guess that including a given header or using reflect operator would bring in the metadata. - I am not sure whether the "reflect" operator is a good idea. First I'd change the name to mirror since reflection is usually employed when the objects know their own metadata, which is not the case here. Then i guess that the operator should return a type, not a value, for easier use in metaprograms. #pragma mirror // (or reflect) struct S { … }; // defines a function that only accepted mirrored types template <class T> typename std::enable_if<mirror(T)::is_defined>::type f(T& t); If a new operator is too much, then a lot could be achieved using only template specialization, but that would not work with namespaces easily. ( mirror<T>::is_defined ...). It's probably Worth mentioning in a proposition. - I guess the "mp" namespace is something in the lines boost::mpl but there's no such thing in the standard yet. You should try to show use cases that are more accessible to main stream programmers and that show useful features without having to write and document a full page of code. Everything is still a bit messy, sorry if I said anything stupid, it's a bit late here. Despite all the criticism, please be assured that I appeciate the huge effort you've been pulling, I have focused on what I think could be improved ;). I'll make more comments later on, when I'll have digested your library a bit better. Regards, Julien

Hi, On Mon, Apr 23, 2012 at 5:03 PM, Julien Nitard <julien.nitard@m4tp.org> wrote:
I am interested a lot in introspection in C++. I have been using another approach (and extended) boost.reflect.
I'd like to participate in the effort. The document is rather lengthy though and I am not done reading (I've been away the past few days).
Nice to hear!
Here are a few comments though:
- Globally you start with the complex stuff. Yes what you did is very powerful and complete, but please consider the user point of view first. I am a user for reflection data and here is what I'd like to see when I am thinking about introspection in C++:
#pragma reflect // generate metadata for the next language element sturct Reflected { int a; string b; double c; };
vector<Reflected> myData;
CsvWriteHeader<Reflected>(myFile); for (auto& entry: myData) CsvWriteLine(myFile, entry);
All the meta programming is very clever but has (IMHO) a smaller target audience, it's the mean, not the purpose. I believe you should start with the purpose then explain how you did it. So as a first piece of advice, I'd show how to reflect a POD (only data members) then a class (methods, static members) then a template and a template instance (if that is possible didn't check yet).
I didn't want the paper to be too long and boring but, you're right I'll add some such examples of usage. One of the design goals is "completeness" i.e. to provide as much meta-data as possible (to a reasonable level) to accommodate also the more obscure use cases for reflection not only the most obvious ones (like serialization, etc.) which might make it "scary" for newcomers. On the other hand I expect that the basic meta-data provided by the compiler (as described by the paper) would be wrapped by some higher-level libraries (like Mirror) that would be more user friendly. This library/libraries would also be part of the standard. Others could be implemented by 3rd parties.
- I think you are neglecting the aspect on how the user can choose the types that are going to be reflected. I believe not all types should have their metadata generated, at least to save on compile time on large projects. The way I did it in my preprocessor was using a pragma directive but it was much simpler than Mirror since it was only intended for classes. There migth be other ways, though, but it should be made more explicit. If reflection makes it into the standard, there shouldn't be any tools to generate the metadata besides the compiler. For the standard library, I guess that including a given header or using reflect operator would bring in the metadata.
Actually, this is one of my primary concerns. I also think that the way to go is not to reflect everything automatically, but to let the user to (somehow) choose what should be reflected. But i think that the process of "marking" namespaces, classes, etc. that should be reflected, should be decoupled from the declaration of the namespace, class, etc. because that would allow greater flexibility and also would allow to cherry-pick, what parts of 3rd-party libraries should be reflected in concrete applications based on their needs. This is mentioned in the "Unresloved issues" section.
- I am not sure whether the "reflect" operator is a good idea. First I'd change the name to mirror since reflection is usually employed when the objects know their own metadata, which is not the case here.
Personally I don't have anything against "mirror" I just didn't want to put any shameless plugs there :) since Mirror is also the name of the library that I'm working on. But I'll go with anything the community here suggests or the Committee decides (if the proposal manages to go that far).
Then i guess that the operator should return a type, not a value, for easier use in metaprograms.
#pragma mirror // (or reflect) struct S { … };
As already said above, I would like this to be decoupled. For example: --- lib-header.hpp: --- namespace ns1 { struct S1 { ... }; struct S2 { ... }; struct S3 { ... }; ... struct Sn { ... }; } // namespace ns1 --- app.cpp: --- #include <lib-header.hpp> // I just want S1, S23 and S42, not the whole library #pragma-or-whatever mirror ns1::S1 ns1::S23 ns1::S42 ... use the metadata provided by reflection here ...
// defines a function that only accepted mirrored types template <class T> typename std::enable_if<mirror(T)::is_defined>::type f(T& t);
The is_metaobject<mirror(T)> type-trait that is proposed in the paper should probably suffice and be implemented with a compiler intrinsic like the other type traits..
If a new operator is too much, then a lot could be achieved using only template specialization, but that would not work with namespaces easily. ( mirror<T>::is_defined ...). It's probably Worth mentioning in a proposition.
This is discussed in the "Reflection" section: - The operator would be "nicer" and more convenient but has a potential to break a lot of existing code. - A (set of) reflection function(s) is not so "powerful" and "nice" but should not break anything.
- I guess the "mp" namespace is something in the lines boost::mpl but there's no such thing in the standard yet. You should try to show use cases that are more accessible to main stream programmers and that show useful features without having to write and document a full page of code.
The paper does not suggest that the Mirror library should be copied verbatim into the standard. But as already said above I expect that there would be such library to make the usage of the meta-data provided by the compiler easier. There actually could be multiple libraries like in the Mirror utilities ranging from compile-time functional-style reflective meta-programming to a dynamically loadable run-time reflection. I definitely plan to update/rewrite Mirror et. al. to use the meta-data once the specification if "polished".
Everything is still a bit messy, sorry if I said anything stupid, it's a bit late here. Despite all the criticism, please be assured that I appeciate the huge effort you've been pulling, I have focused on what I think could be improved ;). I'll make more comments later on, when I'll have digested your library a bit better.
Thank you for your feedback. It is much appreciated and I look forward to any other suggestions you might have. Best, Matus

- I think you are neglecting the aspect on how the user can choose the types that are going to be reflected. I believe not all types should have their metadata generated, at least to save on compile time on large projects. The way I did it in my preprocessor was using a pragma directive but it was much simpler than Mirror since it was only intended for classes. There migth be other ways, though, but it should be made more explicit. If reflection makes it into the standard, there shouldn't be any tools to generate the metadata besides the compiler. For the standard library, I guess that including a given header or using reflect operator would bring in the metadata.
Actually, this is one of my primary concerns. I also think that the way to go is not to reflect everything automatically, but to let the user to (somehow) choose what should be reflected. But i think that the process of "marking" namespaces, classes, etc. that should be reflected, should be decoupled from the declaration of the namespace, class, etc. because that would allow greater flexibility and also would allow to cherry-pick, what parts of 3rd-party libraries should be reflected in concrete applications based on their needs.
Since this is compile-time reflection, can't the compiler generate reflection metadata "on demand" (that is, whenever it is being queried) rather than the user having to explicitly mark classes as reflected, without any loss of efficiency? Regards, Nate

On Mon, Apr 23, 2012 at 6:21 PM, Nathan Ridge <zeratul976@hotmail.com> wrote:
- I think you are neglecting the aspect on how the user can choose the types that are going to be reflected. I believe not all types should have their metadata generated, at least to save on compile time on large projects. The way I did it in my preprocessor was using a pragma directive but it was much simpler than Mirror since it was only intended for classes. There migth be other ways, though, but it should be made more explicit. If reflection makes it into the standard, there shouldn't be any tools to generate the metadata besides the compiler. For the standard library, I guess that including a given header or using reflect operator would bring in the metadata.
Actually, this is one of my primary concerns. I also think that the way to go is not to reflect everything automatically, but to let the user to (somehow) choose what should be reflected. But i think that the process of "marking" namespaces, classes, etc. that should be reflected, should be decoupled from the declaration of the namespace, class, etc. because that would allow greater flexibility and also would allow to cherry-pick, what parts of 3rd-party libraries should be reflected in concrete applications based on their needs.
Since this is compile-time reflection, can't the compiler generate reflection metadata "on demand" (that is, whenever it is being queried) rather than the user having to explicitly mark classes as reflected, without any loss of efficiency?
This is actually mentioned in the "Implementation hints" section, and yes the compiler should generate meta-data lazily, but the problem is that I would like to be able to traverse the members of a scope (namespace, class, ...). You can imagine what would happen if such operation instantiated for example ALL members of the boost or std namespace. There are some ideas on how to solve this in the "Unresolved issues" section but it is rather complicated: - If we allow everything to be reflected the compile-times would be horrible, even worse if a run-time reflection facility was based on this meta-data so would be the resulting executable size. - If we allow some sort of "white-listing" (i.e. specify what you want) or "black-listing" (specify what you don't want) it would be inconvenient for some use-cases. I'm a fan of the "white-list" approach, but I would like to hear your opinions on this issue. BR, Matus

Since this is compile-time reflection, can't the compiler generate reflection metadata "on demand" (that is, whenever it is being queried) rather than the user having to explicitly mark classes as reflected, without any loss of efficiency?
This is actually mentioned in the "Implementation hints" section, and yes the compiler should generate meta-data lazily, but the problem is that I would like to be able to traverse the members of a scope (namespace, class, ...). You can imagine what would happen if such operation instantiated for example ALL members of the boost or std namespace.
I see, good point.
There are some ideas on how to solve this in the "Unresolved issues" section but it is rather complicated:
- If we allow everything to be reflected the compile-times would be horrible, even worse if a run-time reflection facility was based on this meta-data so would be the resulting executable size.
- If we allow some sort of "white-listing" (i.e. specify what you want) or "black-listing" (specify what you don't want) it would be inconvenient for some use-cases.
I'm a fan of the "white-list" approach, but I would like to hear your opinions on this issue.
Whitelisting seems appropriate. To make it more convenient, it would be nice to be able to white-list at different granularities - for example, an entire namespace (meaning all its contents), or just particular elements of a namespace. I also like the idea of separating the whitelisting from the definition of the namespace/class. For example, I may *want* to traverse all the elements of namespace std, so I should be able to whitelist it in my code only. Regards, Nate

There are some ideas on how to solve this in the "Unresolved issues" section but it is rather complicated:
- If we allow everything to be reflected the compile-times would be horrible, even worse if a run-time reflection facility was based on this meta-data so would be the resulting executable size.
- If we allow some sort of "white-listing" (i.e. specify what you want) or "black-listing" (specify what you don't want) it would be inconvenient for some use-cases.
I'm a fan of the "white-list" approach, but I would like to hear your opinions on this issue.
Whitelisting seems appropriate. To make it more convenient, it would be nice to be able to white-list at different granularities - for example, an entire namespace (meaning all its contents), or just particular elements of a namespace.
I also like the idea of separating the whitelisting from the definition of the namespace/class. For example, I may *want* to traverse all the elements of namespace std, so I should be able to whitelist it in my code only.
Yes it may be a legitimate use case to traverse everything and this is where it would be annoying to have to re-specify everything so the white list should allow to use some kind of wildcard even if only for the "get everything" case. The paper describes a tagging mechanism and IMHO some kind of combination of white-listing and compile-time filtering based on the user-specified predicates examining the tags and various properties of the meta-data would be "best". regards, Matus

I'm going to put in my own 2 cents. Right now I'm using metaprogramming to generate fusion::maps as structures. Perhaps one day it'd be better to use something like mirror to go the other way or combine a meta-programatic protocol description with a user defined structure with a subset of the fields he wants. It'd be way easier for a user to deal with a regular structure than a generated fusion::map. 1) Someone mentioned it being problematic to iterate of members of a namespace. I think it souldn't be done since additional compliation scopes can add more to a namespace. Namespaces are open ended. A complete structure should be no problem though. 2) AFAICT mirror doesn't work for templates types or template members. 3) I'm more for a meta-function syntax than an operator. To me mirror<T> seems like a natural extension of type traits. 4) Should mirror< mirror< T > > work? 5) Should conversion ever work the opposite way? Should I be able to meta-programatically generate types from your representation: typedef unmirror< addField< mirror<T>, "member", int> > NewT; Obviously that would require a ton of compiler magic, but might be something to think about. Is your representation easy to manipulate/generate? How cubersome would addField<> be? Chris

On Wed, Apr 25, 2012 at 12:15 PM, Hite, Christopher <Christopher.Hite@partner.commerzbank.com> wrote:
I'm going to put in my own 2 cents. Right now I'm using metaprogramming to generate fusion::maps as structures. Perhaps one day it'd be better to use something like mirror to go the other way or combine a meta-programatic protocol description with a user defined structure with a subset of the fields he wants. It'd be way easier for a user to deal with a regular structure than a generated fusion::map.
1) Someone mentioned it being problematic to iterate of members of a namespace. I think it souldn't be done since additional compliation scopes can add more to a namespace. Namespaces are open ended. A complete structure should be no problem though.
It is true that the list of members of a namespace can be different in two or more translation units based on what headers are included for example. But there are many use-cases where the inspection and traversal of members of a namespace is very useful. I work for example on (a unfortunately closed-source) application that is part of a kind-of-ORM-system which traverses the classes in a namespace and generates SQL DDL commands to create database objects (types, tables, ...) based on the meta-data.
2) AFAICT mirror doesn't work for templates types or template members.
mirror or Mirror :) ? Mirror is not a perfect library. A lot of support from the compiler is necessary to get reflection right.If you are talking about the 'mirror' function/meta-function then, yes that would have its limits too (see 3))
3) I'm more for a meta-function syntax than an operator. To me mirror<T> seems like a natural extension of type traits.
In an ideal world I would prefer the operator, because it would be more "powerful", consistent, "nice", etc., but I see why it may be a bad idea in the current reality. Getting the meta-data for the global scope namespace and arbitrary types should be enough.
4) Should mirror< mirror< T > > work?
There is a MetaMetaObject concept in Mirror, but I've been kind of struggling in its design. It is useful in some cases though.
5) Should conversion ever work the opposite way? Should I be able to meta-programatically generate types from your representation: typedef unmirror< addField< mirror<T>, "member", int> > NewT;
Obviously that would require a ton of compiler magic, but might be something to think about. Is your representation easy to manipulate/generate? How cubersome would addField<> be?
I've also thought about this, IMO such feature would find a lot of use-cases and open "new horizons" :) for compile-time meta-programming, but designing and implementing it might be quite difficult. I'm not sure what the compiler vendors would say to that. Also I don't want the proposal to be too bloated. Too much complexity is IMHO one of the reasons why C++0x concepts were rejected. Best, Matus

Hi again,
4) Should mirror< mirror< T > > work?
There is a MetaMetaObject concept in Mirror, but I've been kind of struggling in its design. It is useful in some cases though.
But I guess limited cases I guess, since there will be just a few types of metaobjects (struct/class, member, function, template, namespace ...)
5) Should conversion ever work the opposite way? Should I be able to meta-programatically generate types from your representation: typedef unmirror< addField< mirror<T>, "member", int> > NewT;
Obviously that would require a ton of compiler magic, but might be something to think about. Is your representation easy to manipulate/generate? How cubersome would addField<> be?
I've also thought about this, IMO such feature would find a lot of use-cases and open "new horizons" :) for compile-time meta-programming, but designing and implementing it might be quite difficult.
I'm not sure what the compiler vendors would say to that. Also I don't want the proposal to be too bloated. Too much complexity is IMHO one of the reasons why C++0x concepts were rejected.
I guess this is not reflection any more, it's code generation. It's already possible to combine types rather easily (don't need the compiler's help) with new fields by using inheritance + CRTP, std::tuple or boost::mpl::vector. The reflection metadata will probably be easy to feed to any meta programming library without the need to add anything to the proposal. … Or am I missing something ? One more thing that's missing from the proposition is annotations (as in "user defined metadata"). I'd be happy to have those as well. An annotation could be a list of objects of arbitrary type associated to a reflected object. The motivational example is formatting an object to XML/Json/CSV to be able to override the default serialization by the user. Doing it without the compiler's help is already possible for some objects (types and members) by specializing a template on the type or pointer to member to be annotated, though I guess some new syntax would be required to make the life of the user easy. Finally (for today ;), you don't mention the interactions of Mirror with RTTI in the paper (though there are some from the docs). I guess it should be possible to get the reflection information from the typeid and vice versa. Regards, Julien

On Thu, Apr 26, 2012 at 5:06 PM, Julien Nitard <julien.nitard@m4tp.org> wrote:
Hi again,
4) Should mirror< mirror< T > > work?
There is a MetaMetaObject concept in Mirror, but I've been kind of struggling in its design. It is useful in some cases though.
But I guess limited cases I guess, since there will be just a few types of metaobjects (struct/class, member, function, template, namespace ...)
AFAICT all the cases where I used the MetaMetaObject could be re-implemented by using the meta-object-traits, so this is IMO not a critical feature.
5) Should conversion ever work the opposite way? Should I be able to meta-programatically generate types from your representation: typedef unmirror< addField< mirror<T>, "member", int> > NewT;
Obviously that would require a ton of compiler magic, but might be something to think about. Is your representation easy to manipulate/generate? How cubersome would addField<> be?
I've also thought about this, IMO such feature would find a lot of use-cases and open "new horizons" :) for compile-time meta-programming, but designing and implementing it might be quite difficult.
I'm not sure what the compiler vendors would say to that. Also I don't want the proposal to be too bloated. Too much complexity is IMHO one of the reasons why C++0x concepts were rejected.
I guess this is not reflection any more, it's code generation. It's already possible to combine types rather easily (don't need the compiler's help) with new fields by using inheritance + CRTP, std::tuple or boost::mpl::vector. The reflection metadata will probably be easy to feed to any meta programming library without the need to add anything to the proposal. … Or am I missing something ?
e Yes, variadic templates + multiple inheritance allow to do similar things even if not all that would be possible with this feature. The above were more musings than a proposal to add the said feature :)
One more thing that's missing from the proposition is annotations (as in "user defined metadata"). I'd be happy to have those as well. An annotation could be a list of objects of arbitrary type associated to a reflected object. The motivational example is formatting an object to XML/Json/CSV to be able to override the default serialization by the user. Doing it without the compiler's help is already possible for some objects (types and members) by specializing a template on the type or pointer to member to be annotated, though I guess some new syntax would be required to make the life of the user easy.
Actually (something similar to) this already IS covered by the paper, for exactly the same reasons that you mention :) See the section 3.4. Annotations and relations and also "Unresolved Issues". What is unresolved is the mechanism of annotations and how exactly it would be reflected by the meta-object, but the latter is a minor problem. It is on the TO DO list.
Finally (for today ;), you don't mention the interactions of Mirror with RTTI in the paper (though there are some from the docs). I guess it should be possible to get the reflection information from the typeid and vice versa.
This is intentional. This proposal deals with static compile-time reflection and RTTI is (mostly) dynamic. On the other hand any run-time reflection facility built on top should cooperate or extend the current RTTI. Best, Matus

One more thing that's missing from the proposition is annotations (as in "user defined metadata"). I'd be happy to have those as well. An annotation could be a list of objects of arbitrary type associated to a reflected object. The motivational example is formatting an object to XML/Json/CSV to be able to override the default serialization by the user. Doing it without the compiler's help is already possible for some objects (types and members) by specializing a template on the type or pointer to member to be annotated, though I guess some new syntax would be required to make the life of the user easy.
C++11 already provides attributes. This could be made reflectable, so attributes could be used by libraries and not just compilers. Thanks, Paul Fultz II

Hi,
One more thing that's missing from the proposition is annotations (as in "user defined metadata"). I'd be happy to have those as well. An annotation could be a list of objects of arbitrary type associated to a reflected object. The motivational example is formatting an object to XML/Json/CSV to be able to override the default serialization by the user. Doing it without the compiler's help is already possible for some objects (types and members) by specializing a template on the type or pointer to member to be annotated, though I guess some new syntax would be required to make the life of the user easy.
C++11 already provides attributes. This could be made reflectable, so attributes could be used by libraries and not just compilers.
Yes, C++11's generalized attributes is one of the options I've been looking into for this puspose. BR, Matus

C++11 already provides attributes. This could be made reflectable, so attributes could be used by libraries and not just compilers.
Yes, C++11's generalized attributes is one of the options I've been looking into for this puspose.
C++11 Attributes are not supposed to change the meaning of the program. The program should still work if the compiler doesn't support them. They may provide optimization hints or info to your gui but can't be used to produce effects. Julien

On Fri, Apr 27, 2012 at 12:36 AM, Julien Nitard <julien.nitard@m4tp.org> wrote:
C++11 already provides attributes. This could be made reflectable, so attributes could be used by libraries and not just compilers.
Yes, C++11's generalized attributes is one of the options I've been looking into for this puspose.
C++11 Attributes are not supposed to change the meaning of the program. The program should still work if the compiler doesn't support them. They may provide optimization hints or info to your gui but can't be used to produce effects.
This is one of the reasons (together with the fact that attributes are part of the declaration and cannot be decoupled from it) why the annotations are still an unresolved issue. Since using attributes for this purpose would require some changes to their specification. BR, Matus

2012/4/20 Matus Chochlik <chochlik@gmail.com>
Afterwards I discussed it with several people including Dean Michael Berris, who is the co-author of n3340 "Rich pointers" and is also interested in adding run-time (and static) reflection to C++. We've decided that we merge the ideas from my paper into his proposal (which has not happened yet and will probably take a while).
Compile-time reflection may be more inline with the spirit of C++, specifically the preference of no-overhead abstractions. Be careful with binding your work too closely with runtime reflection -- don't let it sink your proposal. This might be even more dangerous given that both proposals are quite heavy and will probably take years to mature. Roman.

On Tue, Apr 24, 2012 at 3:31 AM, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote:
Compile-time reflection may be more inline with the spirit of C++, specifically the preference of no-overhead abstractions. Be careful with binding your work too closely with runtime reflection -- don't let it sink your proposal. This might be even more dangerous given that both proposals are quite heavy and will probably take years to mature.
+1

On Mon, Apr 23, 2012 at 8:31 PM, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote:
Afterwards I discussed it with several people including Dean Michael Berris, who is the co-author of n3340 "Rich pointers" and is also interested in adding run-time (and static) reflection to C++. We've decided that we merge the ideas from my paper into his proposal (which has not happened yet and will probably take a while).
Compile-time reflection may be more inline with the spirit of C++, specifically the preference of no-overhead abstractions. Be careful with binding your work too closely with runtime reflection -- don't let it sink your proposal. This might be even more dangerous given that both proposals are quite heavy and will probably take years to mature.
The idea (at least for my part) is that the run-time reflection should be based on the static meta-objects and mostly implemented as a library on top of them with some additional trickery if necessary (similar for example to typeid to allow reflection of polymorphic objects). Maybe Dean can clarify his ideas better, but we have agreed on the "desired features" as described in 3.1 in the paper and also on that everything that can be provided at compile-time should be provided at compile-time (including even strings like identifiers, keywords, etc. if possible).

Hi again, [MC] Personally I don't have anything against "mirror" I just didn't want to put any shameless plugs there :) since Mirror is also the name of the library that I'm working on. But I'll go with anything the community here suggests or the Committee decides (if the proposal manages to go that far). [JN] I guess the proposal should mention the name it thinks is more appropriate. Your library is one of many using that name for that purpose, so no shameless plugs ;) I guess that "mirror" is the proper name since the objects don't reflect themselves, but just my 2 cts. [MC] [About metadata generation] Actually, this is one of my primary concerns. I also think that the way to go is not to reflect everything automatically, but to let the user to (somehow) choose what should be reflected. But i think that the process of "marking" namespaces, classes, etc. that should be reflected, should be decoupled from the declaration of the namespace, class, etc. because that would allow greater flexibility and also would allow to cherry-pick, what parts of 3rd-party libraries should be reflected in concrete applications based on their needs. [JN] I think there's a problem in this. If I summarize, the reflection info is (should) be stored in an immutable global object. That means that it must (should) be declared in a CPP, not a header, like other global (/static) variables. If it is, then the compiler must make sure that is present only once accross various libraries. It may be possible, but I am not sure. If the declaration of the metadata is not linked to the declaration of the object, then the compiler has no way to know whether that info exists and will suppose it does. If it doesn't you'll get a link error. On the other hand if you force the declaration of the metadata at the same time as the type, then the compiler knows whether the metadata exists or not and will result in an earlier error that is probably easier to analyze. Now, if the metadata is only type information it *may* be possible to generate it at will anywhere without linking problem. I guess the proposal should explicit more how all that should work and probably requires some compiler expertise I am far from having. Regards, Julien

Hello,
[MC] Personally I don't have anything against "mirror" I just didn't want to put any shameless plugs there :) since Mirror is also the name of the library
[JN] I guess the proposal should mention the name it thinks is more appropriate. Your library is one of many using that name for that purpose, so no shameless plugs ;) I guess that "mirror" is the proper name since the objects don't reflect themselves, but just my 2 cts.
It is true that 'mirror' is the usual term for "stratified" objects/functions providing meta-data for decoupled base-level objects. I'll update the paper and include some explanation.
[MC] [About metadata generation] Actually, this is one of my primary concerns. I also think that the way to go is not to reflect everything automatically, but to let the user to (somehow) choose what should be reflected. But i think that the process of "marking" namespaces, classes, etc. that should be reflected, should be decoupled from the declaration of the namespace, class, etc. because that would allow greater flexibility and also would allow to cherry-pick, what parts of 3rd-party libraries should be reflected in concrete applications based on their needs.
[JN] I think there's a problem in this. If I summarize, the reflection info is (should) be stored in an immutable global object. That means that it must (should) be declared in a CPP, not a header, like other global (/static) variables. If it is, then the compiler must make sure that is present only once accross various libraries. It may be possible, but I am not sure. If the declaration of the metadata is not linked to the declaration of the object, then the compiler has no way to know whether that info exists and will suppose it does. If it doesn't you'll get a link error. On the other hand if you force the declaration of the metadata at the same time as the type, then the compiler knows whether the metadata exists or not and will result in an earlier error that is probably easier to analyze. Now, if the metadata is only type information it *may* be possible to generate it at will anywhere without linking problem.
I would like the meta-objects to be completely "static" and to provide the meta-information only through types and compile-time constants and be (re-)generated for every translation unit and not shared implicitly between translation units to avoid ODR violations. The libraries based on top of the meta-object provided by the compiler (mostly those implementing run-time reflection) would have to take care of this (avoid ODR violations) themselves.
I guess the proposal should explicit more how all that should work and probably requires some compiler expertise I am far from having.
OK, I'll add this too, thanks. BR, Matus
participants (6)
-
Hite, Christopher
-
Julien Nitard
-
Matus Chochlik
-
Nathan Ridge
-
paul Fultz
-
Roman Perepelitsa