C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Simplified reflection with tuples

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Wed, 3 Jan 2024 16:16:48 -0500
On Wed, Jan 3, 2024 at 3:34 PM Franklin Yang via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> > The "splicing" syntax is for reification: the transformation of a
> > reflection *value* back into the thing it represents.
> You're right, but this only makes splicing more confusing. Why should it iterate (e.g. a class) if it *doesn't* return another reflection value?

But... it doesn't. Splicing doesn't iterate. There was a discussion in
the proposal for a pack expansion version of splicing, but that uses
`...` notation, and it's not actually part of the proposal.

> Transforming a reflection value should be an operation done on the value itself and itself only, like dereferencing a pointer or retrieving the value of a member variable.

... that's what it does.

> > And note that I said "reflection value", not "type".
> I said "reflection type" because that is exactly the language used in P1240 and P2996.
>
> > Why would you want to store a function as a type? Again, you're
> > thinking too much in terms of template metaprogramming.
> I'm not saying that functions *should* be stored as types, but rather that the splicer syntax is considerably weaker for functions, which cannot use the `typename` splicer.

But you wouldn't *want to*. Functions aren't *classes*; they're not
`typename`s. When you reify a function, what you get back... is a
*function*. You know, a thing you can *call*.

Think of it like this:

```
void func(); //This is a function.

auto ref_func = ^func; //This is a reflection of a function.

func some_variable; //This is a compile error because `func` is not a type.

typename[:ref_func:] some_variable; //This is a compile error because
the thing `ref_func` represents is a function, not a type.

func(); //Calls the function
[:ref_func:](); //Calls the function represented by `ref_func`.
```

If you want the type of the function, that's what `decltype` is for.

> > Also, a `tuple` interface only makes sense for reflecting over the
> > contents of an entity. Getting the properties of the entity itself
> > (name, etc) wouldn't be available.
> Of course. Perhaps I was short-sighted when I said that reflection always returns tuple, as this would also not work on single entities. The tuple could be instead relegated to a member of the reflection type.

... why have the tuple there at all? Why not have an array of
reflection values? I can iterate over an array of values; I can't
iterate over a tuple.

> > But the "existing approaches" are all painful and difficult to use.
> Fold expressions and lambdas make dealing with tuples straightforward. It is really not much different from the proposed `template for` except for syntax, and not requiring another language feature.

Anything involving `make_integer_sequence` is not "straightforward".

> > `reflexpr` would also be an operator.
> It wouldn't. The Reflection TS defines reflexpr as a function-like specifier, more like static_cast than co_await. The syntax `reflexpr ::` is not valid, it must be `reflexpr(::)`.

The reflection TS operates on types, not values. That is, if you
reflect over an entity, the result is a type. Every value-based
reflection proposal (where reflection over an entity results in a
value) makes `reflexpr` an expression because expressions result in
values.

That's the nature of value-based reflection rather than type-based reflection.

Received on 2024-01-03 21:17:00