Date: Mon, 2 Jan 2023 21:15:13 -0500
On Mon, Jan 2, 2023 at 8:45 PM Smith, Jim via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Hi All,
>
> Please accept my apology for the late response, very busy. Didn’t want to leave this discussion open ended.
>
> I really appreciate your responses.
>
> >>>> "Private, protected, and public provide control over inheritance of members, which would not be possible by diligence alone (and the lack of "private" would kill interoperability between various code sets by forcing all developers to choose personally unique member variable names to allow subclasses to exist without conflicting with base class should-be-private member names), and the use case for design rule enforcement is enormous as well. Otoh, the access-per-member use case seems rather esoteric (also there are a lot of potential complications especially where inheritance and templating become involved)."
>
> I clearly see a per-member access feature for classes being unnecessary in some cases. Still hiding a class data member from specific methods that don't need to know about is useful.
Repeatedly declaring that this is true in the face of broad skepticism
is not a convincing rhetorical strategy.
As far as I know of, there is no programming language that provides
the specific feature you're talking about. So you can't point at other
languages as examples of where this feature would be useful. All of
your examples are sufficiently abstract that you cannot give a
justification for why it is necessary to *semmantically* forbid access
beyond dogmatically repeating that "data hiding is good".
Dogma is not convincing.
> Also it gives the compiler additional knowledge of how your class' data is being used so may reveal possible optimizations.
What optimizations would those be?
> Unless you're dealing with a single function body, data hiding may be applicable.
What is and is not "applicable" is not the question. The question is
what is practical and meaningful.
> >>>> "But more importantly, and to be blunt, things like private, protected, public, const, override, those all enforce good, effective design patterns. On the other hand, per-member access controls seem to enforce only bad design patterns, where better organization of classes, improved documentation, and testing are the typical good approach. To get to the point where per-member access is necessary, mistakes would have had to have been made, and C++ *tries* (sometimes failing, but it tries) to encourage things that are not mistakes."
>
> Any feature in C++ can be misused, but in general data hiding is good practice regardless of where it's applied. Otherwise we could say Lambdas are bad because we're declaring a function inside a function for the purpose of hiding logic and data. Why not instead add another method to the class of the function using the lambda? This is similar to your argument against the ability to declare a namespace inside a class' body.
No, it isn't. That's not why lambdas exist.
People don't make lambdas to hide data and logic. They make lambdas
because they want to localize functionality in the place where it is
meaningful. That is, you have some block of code that you need to
execute via a callback, but logically speaking, that is part of this
function. The only reason you're making it a function is because
there's some callback interface that needs to use it as a function.
Being a function is an implementation detail.
And as for the captures of a lambda, we don't bubble those up to the
class because those values are *in the function.* You're talking about
taking ephemeral values that will not outlive that instance of the
function (and will also survive recursion) and turning them into
values whose lifetimes are now the class's lifetime. Doing that isn't
a violation of data hiding; it's barfing up the implementation details
of the internals of a function to a level of persistence that is not
what your algorithm actually uses.
> For limiting access to class member types to specific methods inside the same class, I could create a member class type, but there's issues with that approach. For example, in the code below SomeType xyz need to be static and defined or a Namespace class instance must be created:
>
> class Foo {
> public:
> void foo_method0();
> void foo_method1();
>
> struct Namespace {
> friend void foo_method0();
> private:
> SomeType xyz;
> };
> };
>
> Having a feature that allows namespaces in the body of the class will solve this problem.
But it doesn't solve the problem. In both cases, `Foo` will have a
`SomeType` in it, either as a direct member or as a member of another
member. In pretty much every way (save maybe layout), there is no
functional difference.
Also, it is unclear from this code why it is *important* that
`foo_method1` be unable to access `xyz`. It's really important to
understand this point: You can say that a method doesn't use some
member. But that *alone* is not justification for why we should have a
language feature for explicitly forbidding the function from doing so.
<std-proposals_at_[hidden]> wrote:
>
> Hi All,
>
> Please accept my apology for the late response, very busy. Didn’t want to leave this discussion open ended.
>
> I really appreciate your responses.
>
> >>>> "Private, protected, and public provide control over inheritance of members, which would not be possible by diligence alone (and the lack of "private" would kill interoperability between various code sets by forcing all developers to choose personally unique member variable names to allow subclasses to exist without conflicting with base class should-be-private member names), and the use case for design rule enforcement is enormous as well. Otoh, the access-per-member use case seems rather esoteric (also there are a lot of potential complications especially where inheritance and templating become involved)."
>
> I clearly see a per-member access feature for classes being unnecessary in some cases. Still hiding a class data member from specific methods that don't need to know about is useful.
Repeatedly declaring that this is true in the face of broad skepticism
is not a convincing rhetorical strategy.
As far as I know of, there is no programming language that provides
the specific feature you're talking about. So you can't point at other
languages as examples of where this feature would be useful. All of
your examples are sufficiently abstract that you cannot give a
justification for why it is necessary to *semmantically* forbid access
beyond dogmatically repeating that "data hiding is good".
Dogma is not convincing.
> Also it gives the compiler additional knowledge of how your class' data is being used so may reveal possible optimizations.
What optimizations would those be?
> Unless you're dealing with a single function body, data hiding may be applicable.
What is and is not "applicable" is not the question. The question is
what is practical and meaningful.
> >>>> "But more importantly, and to be blunt, things like private, protected, public, const, override, those all enforce good, effective design patterns. On the other hand, per-member access controls seem to enforce only bad design patterns, where better organization of classes, improved documentation, and testing are the typical good approach. To get to the point where per-member access is necessary, mistakes would have had to have been made, and C++ *tries* (sometimes failing, but it tries) to encourage things that are not mistakes."
>
> Any feature in C++ can be misused, but in general data hiding is good practice regardless of where it's applied. Otherwise we could say Lambdas are bad because we're declaring a function inside a function for the purpose of hiding logic and data. Why not instead add another method to the class of the function using the lambda? This is similar to your argument against the ability to declare a namespace inside a class' body.
No, it isn't. That's not why lambdas exist.
People don't make lambdas to hide data and logic. They make lambdas
because they want to localize functionality in the place where it is
meaningful. That is, you have some block of code that you need to
execute via a callback, but logically speaking, that is part of this
function. The only reason you're making it a function is because
there's some callback interface that needs to use it as a function.
Being a function is an implementation detail.
And as for the captures of a lambda, we don't bubble those up to the
class because those values are *in the function.* You're talking about
taking ephemeral values that will not outlive that instance of the
function (and will also survive recursion) and turning them into
values whose lifetimes are now the class's lifetime. Doing that isn't
a violation of data hiding; it's barfing up the implementation details
of the internals of a function to a level of persistence that is not
what your algorithm actually uses.
> For limiting access to class member types to specific methods inside the same class, I could create a member class type, but there's issues with that approach. For example, in the code below SomeType xyz need to be static and defined or a Namespace class instance must be created:
>
> class Foo {
> public:
> void foo_method0();
> void foo_method1();
>
> struct Namespace {
> friend void foo_method0();
> private:
> SomeType xyz;
> };
> };
>
> Having a feature that allows namespaces in the body of the class will solve this problem.
But it doesn't solve the problem. In both cases, `Foo` will have a
`SomeType` in it, either as a direct member or as a member of another
member. In pretty much every way (save maybe layout), there is no
functional difference.
Also, it is unclear from this code why it is *important* that
`foo_method1` be unable to access `xyz`. It's really important to
understand this point: You can say that a method doesn't use some
member. But that *alone* is not justification for why we should have a
language feature for explicitly forbidding the function from doing so.
Received on 2023-01-03 02:15:26