C++ Logo

sg7

Advanced search

Re: [isocpp-sg7] SG7 late paper P3493R0 - Ruminations on reflection and access

From: Herb Sutter <herb.sutter_at_[hidden]>
Date: Tue, 12 Nov 2024 14:31:16 -0500
Peter is saying all the things I want to say (and did say privately).

> TL;DR if we want to prevent accidental misuses of this (unfortunately
quite
> common) sort, what we need is not a function to get the accessible
nonstatic
> data members, but a function that gets the nonstatic data members of a
> struct-like type, and fails for non-struct-like types.

+1, specifically the way I write that is this kind of pattern:

        for( auto&& m: t.get_member_objects() ) {
            if (!m.is_public()) { print_error("type must not have non-public
data"); return; }
            :::
        }

        //
https://github.com/hsutter/cppfront/blob/main/source/reflect.h2#L1046-L1049

But even in that example link, that's Just One of Many Constraints a
metafunction may enforce on a type that it has been given. From just that
particular example, pasting:

        m.require( m.make_public(),
                   "all struct members must be public");
            t.require( !mf.is_virtual(),
                       "a struct may not have a virtual function");
            t.require( !mf.has_name("operator="),
                       "a struct may not have a user-defined operator=");

Serious question: Do we also want to add an API to return only nonvirtual
functions? only non-customized assignment operators? only accessible
members? it all seems very similar to me, in the reflection code I've
written (including all of the above in that single example above) and all of
these are driven by the use case of what code we're going to generate -- and
the code we're going to generate is the key, that's what is going to rely on
the accessibility, non-virtuality, default-assignability, etc. for this
particular use case we're writing the metafunction for.

That is why I'm still open to examples, but so far I'm convinced that
metadata != data, and we routinely need to *reflect* on all *metadata* (and
can then filter exactly what we want no problem) even as I agree that we
also want to be able to avoid *generating* code that bypasses *data*
accessibility by default.

Adding a rule only for reflecting accessible data seems like targeting only
one use case, and doing it at the wrong level (reading metadata, not
accessing data).

I understand smart people disagree, but wanted to reinforce Peter's points.




> -----Original Message-----
> From: SG7 <sg7-bounces_at_[hidden]> On Behalf Of Peter Dimov via SG7
> Sent: Monday, November 11, 2024 10:37 AM
> To: 'Ville Voutilainen' <ville.voutilainen_at_[hidden]>
> Cc: Peter Dimov <pdimov_at_[hidden]>; sg7_at_[hidden]
> Subject: Re: [isocpp-sg7] SG7 late paper P3493R0 - Ruminations on
reflection
> and access
>
> Ville Voutilainen wrote:
> > For an illustrative one, it's far too easy to perform a SoA<=>AoS
> > transformation on a type that doesn't actually expose those types and
> > cardinalities, when most of your types are actually all-public structs
> > and then you manage to throw not-all-public classes into the mix.
>
> I agree that it's easy to write a mostly-working AoS->SoA transformation
that
> only handles structs properly, and that the failure mode of using "get
> accessible nonstatic data members" is better than the failure mode of
using
> "get all nonstatic data members".
>
> In the typical case of a type with only private data members, this would
result
> in an empty SoA type.
>
> Of course, you can see the question "do you really want your
transformation
> to depend on the place where you happen to invoke it" coming, right?
>
> This example is representative for a class of uses where what you really
want
> is not "only do this for the accessible members", and not even "only do
this
> for the public members", but "only do this for types that only have public
> members, reject the rest".
>
> In addition, you also need to take care to reject unions, for which
filtering by
> accessibility won't help you at all, and, in the AoS->SoA case, bitfields.
>
> So filtering by accessibility, while somewhat of an improvement in
catching
> accidental misuses, isn't really what one would ideally want.
>
> Of course, if we really want to do this properly, one might argue that the
> proper transformation of vector<X> for this
>
> class X
> {
> public:
> int a;
> protected:
> int b;
> private:
> int c;
> };
>
> isn't this
>
> struct X'
> {
> vector<int> a';
> }
>
> but rather this
>
> class X'
> {
> public:
> vector<int> a';
> protected:
> vector<int> b';
> private:
> vector<int> c';
> };
>
> Others might argue, in contradiction to the above, that transforming
> vector<complex<float>> into a struct is a perfectly cromulent use case.
>
> TL;DR if we want to prevent accidental misuses of this (unfortunately
quite
> common) sort, what we need is not a function to get the accessible
nonstatic
> data members, but a function that gets the nonstatic data members of a
> struct-like type, and fails for non-struct-like types.
>
> --
> SG7 mailing list
> SG7_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7

Received on 2024-11-12 19:31:22