Date: Sun, 16 Jan 2022 08:21:10 -0500
> On Jan 15, 2022, at 3:00 PM, Matus Chochlik via SG7 <sg7_at_[hidden]> wrote:
>
>
>
> On Sat, Jan 15, 2022 at 8:56 PM Matus Chochlik <chochlik_at_[hidden] <mailto:chochlik_at_[hidden]>> wrote:
> Hi David,
>
> On Sat, Jan 15, 2022 at 8:45 PM David Rector via SG7 <sg7_at_[hidden] <mailto:sg7_at_[hidden]>> wrote:
>
> Now suppose a user decides they want to interface with reflection in an object-oriented style:
> ```
> template<auto R>
> struct DeclWrapper {
> auto nextDecl() { return DeclWrapper <decltype(std::meta::get_next_decl(R))>{}; }
> auto prevDecl() {…}
> auto getParent() { … }
> …
> };
>
> #include … // lots of stuff, big translation unit
>
> int foo;
> constexpr auto foorefl = DeclWrapper <decltype(^foo)>()>();
> ```
>
> What happens when `foorefl` is instantiated?
>
> First each member of DeclWrapper<decltype(^foo)> must be instantiated, which means we have to instantiate each return type, each of which is a DeclWrapper, which itself has to be instantiated, …
>
> The chain reaction results in instantiations of DeclWrappers for *every single declaration in the translation unit*.
>
> I have actually done something like that here:
> https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/metadata.hpp <https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/metadata.hpp>
> and
> https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/registry.hpp <https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/registry.hpp>
>
> for debugging, in order to have a way to easily force the extraction of all metadata and also to see the performance of such "chain reaction".
> To clarify a little more, in my implementation you will not get the reflection of everything in the TU, the cascade is intentionally stopped to prevent really excessive compile-times.
That’s cool, I’m very curious how you stopped the chain reaction, is this a change you made in the compiler, or via cleverness in the library code? I can’t quite figure it out from the links. It would be very nice to offer a solution that users could deploy when constructing their own reflection class hierarchies (and with improvements in constant evaluation performance this desire will surely emerge); I imagine a class attribute, call it something like __attribute__((lazy_instantiate_member_return_types)), would do it.
It would be interesting to see the precise performance hit of a template-instantiation-based approach, relative to the value-based-approach, when this chain-reaction-instantiation issue is guaranteed not to be a factor. Memory usage would still be higher, but just how much would speed suffer, etc. Perhaps the decision to do meta::info and the decision to abjure an object-oriented reflection interface were made simultaneously, possibly giving a distorted impression of the performance gain of the meta::info approach?
As I've said previously it would be best if the language could permit treating templates and classes sufficiently similarly (e.g., allowing one to specify a template name instead of auto as a return type of a dependent function) that template instantiations vs. values could be a compiler implementation issue, rather than a language interface issue.
> --
> SG7 mailing list
> SG7_at_[hidden] <mailto:SG7_at_[hidden]>
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7 <https://lists.isocpp.org/mailman/listinfo.cgi/sg7>
>
>
>
> On Sat, Jan 15, 2022 at 8:56 PM Matus Chochlik <chochlik_at_[hidden] <mailto:chochlik_at_[hidden]>> wrote:
> Hi David,
>
> On Sat, Jan 15, 2022 at 8:45 PM David Rector via SG7 <sg7_at_[hidden] <mailto:sg7_at_[hidden]>> wrote:
>
> Now suppose a user decides they want to interface with reflection in an object-oriented style:
> ```
> template<auto R>
> struct DeclWrapper {
> auto nextDecl() { return DeclWrapper <decltype(std::meta::get_next_decl(R))>{}; }
> auto prevDecl() {…}
> auto getParent() { … }
> …
> };
>
> #include … // lots of stuff, big translation unit
>
> int foo;
> constexpr auto foorefl = DeclWrapper <decltype(^foo)>()>();
> ```
>
> What happens when `foorefl` is instantiated?
>
> First each member of DeclWrapper<decltype(^foo)> must be instantiated, which means we have to instantiate each return type, each of which is a DeclWrapper, which itself has to be instantiated, …
>
> The chain reaction results in instantiations of DeclWrappers for *every single declaration in the translation unit*.
>
> I have actually done something like that here:
> https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/metadata.hpp <https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/metadata.hpp>
> and
> https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/registry.hpp <https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/registry.hpp>
>
> for debugging, in order to have a way to easily force the extraction of all metadata and also to see the performance of such "chain reaction".
> To clarify a little more, in my implementation you will not get the reflection of everything in the TU, the cascade is intentionally stopped to prevent really excessive compile-times.
That’s cool, I’m very curious how you stopped the chain reaction, is this a change you made in the compiler, or via cleverness in the library code? I can’t quite figure it out from the links. It would be very nice to offer a solution that users could deploy when constructing their own reflection class hierarchies (and with improvements in constant evaluation performance this desire will surely emerge); I imagine a class attribute, call it something like __attribute__((lazy_instantiate_member_return_types)), would do it.
It would be interesting to see the precise performance hit of a template-instantiation-based approach, relative to the value-based-approach, when this chain-reaction-instantiation issue is guaranteed not to be a factor. Memory usage would still be higher, but just how much would speed suffer, etc. Perhaps the decision to do meta::info and the decision to abjure an object-oriented reflection interface were made simultaneously, possibly giving a distorted impression of the performance gain of the meta::info approach?
As I've said previously it would be best if the language could permit treating templates and classes sufficiently similarly (e.g., allowing one to specify a template name instead of auto as a return type of a dependent function) that template instantiations vs. values could be a compiler implementation issue, rather than a language interface issue.
> --
> SG7 mailing list
> SG7_at_[hidden] <mailto:SG7_at_[hidden]>
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7 <https://lists.isocpp.org/mailman/listinfo.cgi/sg7>
Received on 2022-01-16 13:21:13