C++ Logo

sg7

Advanced search

Re: [SG7] From TMP to value-based reflection

From: Matus Chochlik <chochlik_at_[hidden]>
Date: Thu, 9 Dec 2021 19:20:10 +0100
On Thu, Dec 9, 2021 at 10:43 AM Jean-Baptiste Vallon Hoarau via SG7 <
sg7_at_[hidden]> wrote:

> Besides the thing that Peter mentioned in another response, something like
>> this didn't work either when I played with the meta::info implementation:
>> ```
>> auto unreflect_type(meta::info mo) {
>> return std::type_identity<typename [: mo :]>{};
>> }
>> ```
>> i.e the return type cannot depend on a non-template meta::info value. You
>> basically have to create a separate consteval function that creates and
>> returns the metaobject. This limits how the metaobjects are passed around
>> in a composition of metaprogramming algorithms. You probably can
>> work-around this by making all the metaprogramming algorithms templates,
>> but is sort-of defeats the thing where all metaobjects are of a single type
>> (meta::info) and In the end it's almost the same as what the "mirror"
>> header does.
>>
>
> Yes, but this is by design. meta::info objects as function parameters
> belongs to (just like other functions parameters) the evaluation-time
> world, not instantiation-time. Indeed metaprogramming with the meta::info
> proposal implies that, if the output of your metaprogramming algorithm
> depends on the type of your reflection, then it must return something which
> must then be injected in the context where that value is an
> instantiation-time construct.
>

So IIUC the difference that we're talking about is the following:
```
// type-based metaobjects ---------------------------

template <typename T>
string_view classify(type_identity<T>) { return "a type"; }
template <typename T>
string_view classify(type_identity<T*>) { return "a pointer type"; }
template <typename T>
string_view classify(type_identity<unique_ptr<T>>) { return "a smart
pointer"; }

auto transform(auto mo) {
  return do_(something(complicated(with(mo))));
}

auto get_type_id(auto mo) {
  return
type_identity<do_t<something_t<here_t<unreflect(transform(mo))>>>>{};
}

string_view my_algo(auto mo) {
  return classify(get_type_id(mo));
}

// meta::info metaobjects ------------------------

template <typename T>
consteval string_view classify(type_identity<T>) { return "a type"; }
// ...

consteval meta::info transform(meta::info mo) {
  return do_(something(complicated(with(mo))));
}

consteval string_view my_algo(meta::info mo) {
  return classify(type_identity<do_t<something_t<here_t<[: mo :]>>>>{});
}
```
A function like the `get_type_id` above cannot be implemented in pure
consteval. This is IMO a pretty big limitation if the thing that is done in
`get_type_id` is really complex and it is used in many places.
(Actually I'm not even sure if the `my_algo` function could be implemented
without being a template, because it depends on the consteval argument.
I'll have to try the meta::info implementation).


> This does not defeat the purpose of operating over uniformly typed values.
> For example, imagine a meta-function which generates the code needed to
> serialize any value. With the meta::info proposal, the whole meta-function
> never needs to be instantiated, simply evaluated, and then the returned
> fragment is injected (a task essentially equivalent to instantiation) into
> the caller's context.
>
I've heard this reasoning before and I'm still not sure what advantages
does this bring over template function instantiation, since as you say
(evaluation + injection = almost like instantiation).

Received on 2021-12-09 12:20:26