Date: Mon, 11 Nov 2024 05:46:26 +0200
> https://isocpp.org/files/papers/P3493R0.html
"There are suggestions that it's enough to access-control data, and leave metadata (types, names, cardinalities) fully-accessible.
That suggestion also doesn't model how the language works. Access controls control metadata as well as data. You can't name the data members of PolarRep/VectorRep/C1/C2/C3/C4, you can't get their types, you can't count how many such members exist; you do not have access to the metadata any more than you have access to the data.
And of course you don't."
I have a few things to say about this.
First, at present, "of course" you don't have access
to anything reflected. That's exactly what we're trying
to fix with 2996.
Second, the principle here is that if I can physically see
in the source code that the class has private members of
types C1, C2, C3, then the program should also be able to
see that, using the reflection facilities. If not, we don't
really have reflection, and we'll have to use other means,
such as parsing the source with libclang, or parsing the
debug info, and so on. Basically, what we do today and
hope we wouldn't need to do tomorrow.
Third, there are many useful things you can do with
metadata access, that aren't computing a hash value.
For instance, many type properties are of the form
"the type is X if all its nonstatic members and base
classes are X", and it's good if we can compute those
ourselves, instead of submitting a WG21 proposal for
a new type trait each time, and waiting 27 years.
Fourth, exposing only the accessible members and
silently pretending that the inaccessible ones don't
exist is not how the language works. This doesn't quite
give the right result in a number of cases. For example,
if you write a function
void call( X& x, char const* name, double v );
and then invoke it on this X
class X
{
private:
void f( double );
public:
void f( int );
};
passing "f" and 1.0, it would result in a call to f(int) if
f(double) is silently omitted, which is not what would
happen if you invoke `x.f(1.0)` directly.
Similar issues occur with
struct B
{
void f(double);
};
class X: public B
{
private:
void f(double);
};
and a number of other examples.
Fifth, strongly against whatever P3493 is proposing.
Sixth, you can't even write memberwise_hash without
metadata access, although I suppose this can be fixed
by making everything mentioned in class(...) a friend.
Seventh, it's useful to know whether a class has
private nonstatic data members, as this is an indication
that it has an invariant and shouldn't be treated as
a struct. If private members are silently omitted, it's
not possible for the program to know that.
"There are suggestions that it's enough to access-control data, and leave metadata (types, names, cardinalities) fully-accessible.
That suggestion also doesn't model how the language works. Access controls control metadata as well as data. You can't name the data members of PolarRep/VectorRep/C1/C2/C3/C4, you can't get their types, you can't count how many such members exist; you do not have access to the metadata any more than you have access to the data.
And of course you don't."
I have a few things to say about this.
First, at present, "of course" you don't have access
to anything reflected. That's exactly what we're trying
to fix with 2996.
Second, the principle here is that if I can physically see
in the source code that the class has private members of
types C1, C2, C3, then the program should also be able to
see that, using the reflection facilities. If not, we don't
really have reflection, and we'll have to use other means,
such as parsing the source with libclang, or parsing the
debug info, and so on. Basically, what we do today and
hope we wouldn't need to do tomorrow.
Third, there are many useful things you can do with
metadata access, that aren't computing a hash value.
For instance, many type properties are of the form
"the type is X if all its nonstatic members and base
classes are X", and it's good if we can compute those
ourselves, instead of submitting a WG21 proposal for
a new type trait each time, and waiting 27 years.
Fourth, exposing only the accessible members and
silently pretending that the inaccessible ones don't
exist is not how the language works. This doesn't quite
give the right result in a number of cases. For example,
if you write a function
void call( X& x, char const* name, double v );
and then invoke it on this X
class X
{
private:
void f( double );
public:
void f( int );
};
passing "f" and 1.0, it would result in a call to f(int) if
f(double) is silently omitted, which is not what would
happen if you invoke `x.f(1.0)` directly.
Similar issues occur with
struct B
{
void f(double);
};
class X: public B
{
private:
void f(double);
};
and a number of other examples.
Fifth, strongly against whatever P3493 is proposing.
Sixth, you can't even write memberwise_hash without
metadata access, although I suppose this can be fixed
by making everything mentioned in class(...) a friend.
Seventh, it's useful to know whether a class has
private nonstatic data members, as this is an indication
that it has an invariant and shouldn't be treated as
a struct. If private members are silently omitted, it's
not possible for the program to know that.
Received on 2024-11-11 03:46:32