C++ Logo

sg7

Advanced search

Re: Scalable reflection - questions / comments

From: Matus Chochlik <chochlik_at_[hidden]>
Date: Tue, 1 Feb 2022 08:39:08 +0100
On Tue, Feb 1, 2022 at 8:05 AM Barry Revzin <barry.revzin_at_[hidden]> wrote:

> I'm not an author of P1240, but...
>
> On Tue, Feb 1, 2022 at 12:24 AM Matus Chochlik via SG7 <
> sg7_at_[hidden]> wrote:
> ADL still works on std::meta::info, so is_named(^int) is valid by itself.
>
OK, good.


>
>> 2) is it / will it be possible for the "filters" in members_of to be
>> lambdas or other boolean-returning callables?
>>
>
> I think that's the point, yeah. As opposed to?
>
I see. I was confused by what is for example the
`is_nonstatic_data_member` `members_of(class_type,
is_nonstatic_data_member)`. It might be useful to have an example with a
lambda in the paper.

Another question, can I do unreflection in that lambda?
members_of(^foo, [](info mo) { return another_predicate([: transform(mo)
:]); });

>
>
>>
>> 3) I have found that there are many use-cases (implementing RPC
>> boilerplate, implementing SQL generator, implementing the factory pattern,
>> and more) where there is a set of functions like foo, bar, baz that are
>> calling each other, which operate on `reflections` (of base-level "things"
>> that are not reified on the base level, like a constructor, a namespace, an
>> expression) that are passed from outside to the algorithm, and
>> splicing is done in the innermost function.
>> pseudocode:
>>
>> auto baz(metaobject auto mo) {
>> return do_something([: mo :]);
>> }
>>
>> auto bar(metaobject auto mo, auto arg1, auto arg2) {
>> return baz(transform1(transform2(mo, arg2), arg1);
>> }
>>
>> auto foo(metaobject auto mo, auto arg1, auto arg2. auto arg3) {
>> return bar(transform3(mo, arg3));
>> }
>>
>> cout << foo(^std, 1, '2', "3");
>>
>> Is it correct that the only way to do this with meta info is to pass the
>> metaobject in template arguments?
>>
>
> Can you provide a more real example?
>
Sure (RPC):
The place where the algo is implemented:
https://github.com/matus-chochlik/mirror/blob/32a0ee8247dce57f51b40e8cb9c5ebe1aa5d02f6/example/mirror/fake_rpc.cpp#L58
The place where the algo is called (note that a reflection of an expression
is passed down, which cannot be done on the base-level):
https://github.com/matus-chochlik/mirror/blob/32a0ee8247dce57f51b40e8cb9c5ebe1aa5d02f6/example/mirror/fake_rpc.cpp#L128

Similar thing here:
implementation:
https://github.com/matus-chochlik/mirror/blob/32a0ee8247dce57f51b40e8cb9c5ebe1aa5d02f6/example/mirror/sql_query_generator.cpp#L35
invocation:
https://github.com/matus-chochlik/mirror/blob/32a0ee8247dce57f51b40e8cb9c5ebe1aa5d02f6/example/mirror/sql_query_generator.cpp#L70

In there a reflection of a constructor is passed around:
https://github.com/matus-chochlik/mirror/blob/develop/include/mirror/factory/builder.hpp

I've done this same thing with the lock3/meta implementation and it
required some ugly workarounds in some places (I've presented it in SG7
some time ago).

>
>
>>
>> template <std::meta::info mo> auto baz() {
>> return do_something([: mo :]);
>> }
>> template <std::meta::info mo> auto bar(auto arg1, auto arg2) {
>> return bar<transform1<transform2<mo>(arg2)>(arg1)>();
>> }
>> template <std::meta::info mo> auto foo(auto arg1, auto arg2, auto arg3) {
>> return bar<transform3<mo>(arg3)>(arg1, arg2);
>> }
>>
>> cout << baz<^std>(1, '2', "3")
>>
>
> I suppose the real question is: Does this work?
>
> consteval auto f(std::meta::info type) {
> return sizeof([:type:]);
> }
>
> And the answer is no: in the paper, [: refl:] is only valid if refl is a
> constant expression. Which, until we get constexpr function parameters,
> means it must be passed as a template parameter.
>

So, what is the timeline on that?
Will such parameters be faster to compile than say using
`wrapper<meta::info>` and if so can the same technique be used to improve
compile-time performance of `__maybe_builtin_wrapper<meta::info>`?

Received on 2022-02-01 07:39:21