C++ Logo

sg7

Advanced search

Re: Scalable reflection - questions / comments

From: Daveed Vandevoorde <daveed_at_[hidden]>
Date: Tue, 1 Feb 2022 09:38:12 -0500
> On Feb 1, 2022, at 1:24 AM, Matus Chochlik via SG7 <sg7_at_[hidden]> wrote:
>
> Hi,
>
> I have the following questions about P1240R2:
>
> 1) std::info::meta and ADL
>
> int main() {
> using std::meta; // is either this
> using std::meta::is_named; // or this necessary
> if constexpr (is_named(^int)) { // for this to compile?
> }
> }


They are not necessary under the proposal because std::meta is an associated namespace of std::meta::info.

>
> 2) is it / will it be possible for the "filters" in members_of to be lambdas or other boolean-returning callables?

Yes.


>
> 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?


For splicing, yes.

See also P1717, which layers injection on top of the facilities of P1240 (well, an earlier version of it): That doesn’t have the constraint.



>
> 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")
>
> Comments:
>
> I agree that performance or reflection API is important, and I agree that the fundamental primitive reflection operations like name_of, etc. should be value-based consteval functions (or maybe builtins). However I think that we are sacrificing usability, readability and the possibility to write a library of complex reflection algorithms (see q.3 above) just for some increase in performance, if the only representation of metaobjects is std::meta::info.

It’s not just a matter of performance (as in one is Nx faster than the other); It’s a matter of scalability: The more ambitious the meta programming project, the larger the discrepancy.


>
> I'd also suggest doing compile-time measurements and comparisons with other approaches on *real-life* use-cases (I don't think that simple programs will do 10k+ reflection operations) and in larger programs the cost of reflection will typically be only a small fraction of the compilation time.


Oh, I very much disagree with that. And we have historical precedent.

When we first started documenting TMP techniques, we said the exact same thing (I was one of them): "This is a bit cumbersome, but it’s just for small utilities that will be encapsulated and whose cost is entirely fine”. And here we are now, with developers complaining about the compile times of their heavily meta-programmed code, and others reporting about compilers running out of memory.

I predict the same will happen with reflective meta programming: Once we have it, libraries will apply it at increasingly larger scales. 10k reflection operations is already entirely realistic today… I expect we’ll see _many millions_ per translation unit.

An additional effect, here, I suspect, is that we will increasingly see “core language feature” proposals morph into “reflective-metaprogrammed library feature” proposals (because the core language syntax space is getting crowded). See for examples the proposals for meta programmed annotations/attributes (P1887), Herb’s meta classes proposal (P0707), etc.

Metaclasses alone is likely to put reflection on the critical path of future modern C++ compilation performance.

 Daveed

Received on 2022-02-01 14:38:14