C++ Logo

sg7

Advanced search

Re: Update: P1240R2 — Scalable Reflection

From: David Rector <davrec_at_[hidden]>
Date: Wed, 19 Jan 2022 09:24:47 -0500
> On Jan 18, 2022, at 11:45 AM, Daveed Vandevoorde via SG7 <sg7_at_[hidden]> wrote:
>
>
>
>> On Jan 18, 2022, at 5:24 AM, Andrey Davydov <andrey.davydov_at_[hidden] <mailto:andrey.davydov_at_[hidden]>> wrote:
>>
>> On Tue, Jan 18, 2022 at 1:09 AM Daveed Vandevoorde <daveed_at_[hidden] <mailto:daveed_at_[hidden]>> wrote:
>>> On Jan 16, 2022, at 8:36 AM, Andrey Davydov <andrey.davydov_at_[hidden] <mailto:andrey.davydov_at_[hidden]>> wrote:
>>>
>>> I wonder what is the lifetime of underlying storage referenced by std::span returned from such functions as std::meta::members_of? Is this array persisted throughout the compilation process?
>> That’s a good question (and one of the reasons I was reluctant to make the vector->span change at first).
>>
>> An implementation is of course free to recompute the array if it needs to. However, if the array “leaks” outside constant-evaluation, it is likely to be made persistent, but doesn’t leak.
>>
>> I don’t expect span<info> objects to typically “leak”, but the “string_view” objects yes.
>>
>> Thanks for the response!
>>
>> I agree that `string_view` could easily "leak", a function `std::string_view to_string(Enum auto e);` is one of such examples,
>
> Exactly.
>
>> but I don't see how to use `span<info>` outside of constant-evaluation, because `meta::info` couldn't be used in runtime and `span<info>` is not a structural type and so couldn't be used as NTTP.
>
> Someone might be tempted to write:
>
> constexpr auto mems = members_of(^S);
>
> and then later feed that to some other reflection algorithm, I suppose. Our implementation will then make the underlying array persistent for the compilation.

I either cannot find or don’t have access to the revised paper, so apologies if this was discussed therein, but: can you comment on the choice to return a span instead of a non-random-access range object? (I.e. provide a begin() and an end(), but no size(), operator[](size_t), etc.?)

Returning a range would allow implementations to use their existing AST storage, minimizing overhead. Clang stores member declarations as a linked list; to return a span it would have to allocate a declaration’s members additionally as an array somewhere, if those members are reflected.

Returning a range would require an additional `meta::info_iterator` type. The user would need to be able to create their own non-const versions of this of course, dereferencing to non-const meta::infos. No problem there, right?

The main benefit I can see to requiring random-access storage is that it would help in the implementation of template-for expansions and probably other expansions like splices of parameter packs. E.g. `for(constexpr auto mem : members_of(^S))` is implemented as a sequence of implicit instantiations looking like this:
```
{
  constexpr auto mem = *std::next(0, members_of(^S).begin())
  // loop body
}
{
   constexpr auto mem = *std::next(1, members_of(^S).begin())
  // loop body
}
...
```
which, if the underlying storage of members_of(^S) is not random access, requires quadratic instead of linear time.

But these implementation details are hidden; if that is the only reason for returning a span compilers could instead be asked to deal with the problem on their own.

Are there other good reasons to return a span instead of a range? Is the ease of use worth the overhead? (Mainly I just want to ensure this choice has been carefully considered; I’m not necessarily arguing for a change.)

>
> Also, I’m still hoping that we will have more facilities to have “compile-time variables” as proposed in P0596R1 some day.
>
>>
>> Moreover, if the lifetime of underlying storage returned by meta::members_of is underspecified then implementation of `get_base_types` in the example on page 46 looks quite suspicious. It's not obvious why it's valid to modify span elements inplace:
>>
>> auto result = bases_of(...);
>> for (auto &info : result) {
>> info = type_of(info);
>> }
>> return result;
>
>
> Good catch. That code was added before the transition and I forgot to update it. Thanks again!
>
> Daveed
>
>>
>> IMO it would be more correct to return `vector<info>` instead of `span<info>` until there is no concrete motivation to do the latter.
>>
>> --
>> Andrey Davydov
>
> --
> 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-19 14:24:50