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