C++ Logo

sg7

Advanced search

Re: Scalable reflection - questions / comments

From: Matus Chochlik <chochlik_at_[hidden]>
Date: Wed, 2 Feb 2022 14:13:25 +0100
Hi SG7,

On Tue, Feb 1, 2022 at 5:53 PM Matus Chochlik <chochlik_at_[hidden]> wrote:

>
> template <typename T>
> concept metaobject = __unspecified__
>
> consteval bool some_predicate(metaobject auto mo);
> consteval auto some_operation(metaobject auto mo);
>
> and later when the consteval arguments are available just say:
>
> template <typename T>
> concept metaobject = is_same_v<T, meta::info>;
>
> I started writing a paper with details, but it won't be ready for
> tomorrow's SG7 telco.
>
> This morning I made some changes to the clang compiler and the `mirror`
library implementation and determined that it is possible to do some
additional optimization with the template-wrapped metaobject id (like
meta::info):

assume that:
 - __metaobject_id is basically the same thing as meta::info
 - mirror(expr) is like ^T but doesn't "return" __metaobject_id directly,
instead it returns a publicly unspecified type that is implemented as:
```
template <__metaobject_id M>
struct wrapped_metaobject {
    consteval operator __metaobject_id() const { return M; }
};
```
Then all the metaobject operations like get_name, is_static, etc. etc.
which do not require instantiation context,
and do not return other metaobjects (there are dozens and there may be
potentially hundreds such functions)
can be internally implemented as:
```
consteval auto is_static(__metaobject_id) -> bool;
consteval auto get_name(__metaobject_id) -> string_view;
```

the functions that require instantiation contexts or return other
metaobjects are implemented as:
```
template <__metaobject_id M>
consteval auto get_scope(wrapped_metaobject<M>) -> wrapped_metaobject<...>;
```

All the other algorithms like `for_each`, `filter`, `fold`, etc. etc. that
mostly require instantiation contexts (because they can take
predicate/transform/etc lambdas that do splicing) keep working after this
change.

Formally all those functions could be defined as

```
template <typename T>
concept metaobject = ...;

consteval auto is_static(metaobject auto) -> bool;
consteval auto get_name(metaobject auto) -> string_view;
consteval auto get_scope(metaobject auto);
```
...without specifying the meta::info or wrapped_metaobject types.

The API is always used as:

foo(bar(baz(mirror(int)));

and *not* like:

foo<bar<baz<^T>()>()>();

There is one notable consequence: span<meta::info> cannot be used right
now. But there are alternatives. In the TS there are the
_metaobject-sequences_ that are expanded, iterated, filtered, etc. lazily
(and I think we should keep them even in this new API, there are use cases
where the contained metaobjects are not required only their count for
example), `template for` could be implemented for such metaobject-sequences
pretty easily as well.

I haven't converted everything, only a small part of potential candidates,
but initial measurements indicate that the compilation times for the
extreme cases where almost all reflection operations are invoked now
compile ~10% faster than previously.

--Matus

Received on 2022-02-02 13:13:37