C++ Logo

sg7

Advanced search

Re: [SG7] string. vector vs string_view, span in reflection API

From: Jean-Baptiste Vallon Hoarau <jeanbaptiste.vallon_at_[hidden]>
Date: Mon, 12 Apr 2021 19:23:36 +0200
>
> This is true — looping over the entire members_of, with a condition
> inside, seems to be 2-3x slower in this example:
>
> https://cppx.godbolt.org/z/bxGhGPfKo
>
> Presumably this is due to the cost of instantiating each body of the
> `template for`, which involves considerable allocations of its own
> internally (e.g. lots of Stmt::Create(…) inside clang).
>

David : I am unable to reproduce your results (the left side with a
condition inside the loop is faster for me, which i think wasn't what you
meant?).
Also, the template for is not needed here, but replacing it by a simple for
doesn't change the result (i suppose the compiler doesn't instantiate any
statements since the body of the loop can simply be evaluated).

Le sam. 10 avr. 2021 à 05:01, David Rector via SG7 <sg7_at_[hidden]> a
écrit :

>
>
> On Apr 9, 2021, at 9:09 PM, Matus Chochlik via SG7 <sg7_at_[hidden]>
> wrote:
>
> On Sat, Apr 10, 2021 at 2:20 AM David Rector <davrec_at_[hidden]> wrote:
>
>>
>>
>> On Apr 9, 2021, at 8:35 AM, Matus Chochlik via SG7 <sg7_at_[hidden]>
>> wrote:
>> This still happens at compile-time inside of the compiler, so it could
>> allocate the filtered range of metaobjects by using some internal
>> mechanism, that is not exposing generic "dynamic" allocation in consteval.
>> Just saying, in case solving dynamic allocation in constexpr/consteval
>> contexts is something blocking us moving forward with reflection.
>> Or am I missing something?
>>
>>
>>
>> To go further, why should the API include something that requires these
>> allocations in the first place, since they don’t seem particularly
>> efficient (or at least won’t scale well) even if the compiler can handle
>> them internally?
>>
>> That is, should we really be encouraging users to use things like
>> `meta::members_of(reflection, predicate)`, which always necessitates a new
>> allocation?
>>
>> It would be more efficient, and permit more natural programming, to only
>> expose `meta::members_of(reflection)` (i.e. no predicate argument) and
>> instead encourage the user to condition actions on those members via
>> control flow statements during iteration over the compiler’s
>> already-allocated container of members.
>>
>> This would require expanding the contexts in which `consteval {}`
>> metaprograms are permitted, and introducing corresponding fragment kinds to
>> permit injection of entities in those contexts.
>>
>> That is the precisely the argument of this paper:
>> https://isocpp.org/files/papers/P2353R0.html, a cleaned up version of
>> the paper “The syntactic gap” I shared on here awhile ago, which should
>> appear in the next mailing.
>>
>> Matus here is how I would write your `unpack_range`, using P2353 features:
>>
>> ```
>> template <std::experimental::meta::info MO>
>> consteval auto unpack_range() {
>> return unpacked_range<
>> consteval {
>> template for (auto mem : meta::members_of(MO))
>> if (meta::is_constructor(mem))
>> << ^<frag::targ>{ mem }; //a template argument fragment
>> }
>> >{};
>> ```
>>
>> This requires no allocations and is simple to read and write.
>>
>> Something to consider moving forward, given the emphasis on efficiency.
>>
>
> I'm just guessing about Andrew and Wyatt's or Daveed and Faisal's
> motivations here, but based on my reflection implementation experience I'd
> say the reason why we want to do some of the filtering inside of the
> compiler might be that "materializing" the whole:
>
> meta::members_of(MO)
>
> that can then be filtered with arbitrary consteval C++ code may be quite
> "heavy" for some meta-objects. for example if:
>
> auto MO = ^std;
> //or
> auto MO = ^boost;
>
>
> This is true — looping over the entire members_of, with a condition
> inside, seems to be 2-3x slower in this example:
>
> https://cppx.godbolt.org/z/bxGhGPfKo
>
> Presumably this is due to the cost of instantiating each body of the
> `template for`, which involves considerable allocations of its own
> internally (e.g. lots of Stmt::Create(…) inside clang).
>
> So `members_of(refl, predicate)` is indeed useful.
>
> The only point here then is that consteval {} and fragments as described
> in P2353 would allow writing your unpack_range example as:
>
> ```
> template <std::experimental::meta::info MO>
> consteval auto unpack_range() {
> return unpacked_range<
> consteval {
> template for (auto mem : meta::members_of(MO,
> meta::is_constructor))
> << ^<frag::targ>{ mem }; //a template argument fragment
> }
> >{};
> ```
>
>
>
> and I do think that reflecting namespaces and getting (some of) their
> members has valid and useful use-cases.
> When I did the POC implementation for what became the TMP-based reflection
> TS I had metaobject-sequences (or ranges) be meta-objects themselves and
> instantiated the elements lazily. It worked with classes, etc. but I don't
> have much data for reflected namespaces.
>
> --Matus
>
> --
> SG7 mailing list
> SG7_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7
>
>
> --
> SG7 mailing list
> SG7_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7
>

Received on 2021-04-12 12:23:49