C++ Logo

sg7

Advanced search

Re: [SG7] Update: P1240R2 — Scalable Reflection

From: Matus Chochlik <chochlik_at_[hidden]>
Date: Sun, 16 Jan 2022 08:35:02 +0100
On Sat, Jan 15, 2022 at 11:34 PM Peter Dimov via SG7 <sg7_at_[hidden]>
wrote:

> David Rector wrote:
> > There is also the matter of a) iteration,
>
> From my perspective (which is trying to get something
> working without being able to patch my own compiler),
> one interesting property of using info<__id> is that one
> can obtain iteration without having `template for`.
>
> Range-returning functions can just return list<__i1, __i2,
> ..., __in>, which can then be iterated using fold
> expressions (or mp_for_each).
>
> I understand that this is quite contrary to the value-based
> "ideology", but it's often more usable. Consider, for
> instance, the use case of taking a struct and making a
> tuple out of it.
>
> (pseudocode:)
>
> template<class S> auto struct_to_tuple( S const& s )
> {
> return struct_to_tuple_impl(s, members_of(^S));
> }
>
> template<class S, template<auto...> class L, auto... R>
> auto struct_to_tuple_impl( S const& s, L<R...> )
> {
> return std::make_tuple( s.*pointer_to( R{} )... );
> }
>
> Of course, it might be possible to implement this with
> ease using P1240/P2320 range splicing; if so, it will make
> a good example.
>

Admittedly, not being able to write an "almost normal" for loop over a
range of metaobjects for now, is a usability issue but:
a) the template for that David has worked on does solve that and would IMO
be quite useful to have.
b) as Peters says there are workarounds and in the end I didn't miss that
too much.

Also, in recent years I have seen multiple talks where people recommended
using named algorithms like filter, for_each, transform, fold, find_if,
etc. whenever possible instead of writing for loops. This both clarifies
the intent of the composite algorithm and may give the compiler a chance to
do some tricks and optimizations. Such algorithms are easily implementable
in an API like mirror.

Another thing is, that an instantiation context is required quite often.
Unreflection is pretty common in many use cases (which IMO diminishes the
potential performance gains) and also highlights the usability issue,
namely IIUC ADL doesn't kick in and much more of full name qualification is
required,

when composing functions like:
meta::info foo<meta::info>();
meta::into bar<meta::info>();
meta::into baz<meta::info>();
into algorithms it looks like:

std::meta::foo<std::meta::bar<std::meta::baz<^something>>>();

with functions taking something like info<__id>:
auto foo(metaobject auto mo);
auto barmetaobject auto mo);
auto baz(metaobject auto mo);
they compose more nicely:

foo(bar(baz(mirror(something)));

and this also allows to write nicer placeholder expressions like:

auto my_algo = foo(bar(baz(_1)));
...
my_algo(mirror(something));
my_algo(mirror(something_else));

There are many examples (and I have some more in the pipeline) of this here
:
https://github.com/matus-chochlik/mirror/tree/develop/example

--Matus

Received on 2022-01-16 07:35:14