Topic: Nested class access - is the DR #45 resolution too extreme?


Author: Rick Wheeler <rwheeler@oyogeospace.com>
Date: Wed, 29 Aug 2007 13:23:05 CST
Raw View
Granting nested classes unrestricted access to their surrounding class
in a gratituitous and non-declarative manner does in fact seem
excessive to me. Most reasoning follows the observation that nested
classes are members and thus entitled to it. However, membership is
not a universal monolith, and distinctions already exist between
member definitions vs dereferenceable elements. Thus there is no
definitive reason to expect such entitlement. Moreover, bulldozing
properties of membership into a flat landscape is neither elegant nor
beneficial to the evolution of the language. The best approach
continues to be the use and refinement of explicit constructs already
available through the "friend" relationship. There seem to be two
esoteric impediments in this regard.

Problem 1: As members, nested classes are not candidates for
firendship.
Solution 1: Assure that "nested classes" is included in the list of
candidates.

Problem 2: Friendship is not transitive, so nested classes are limited
in their own implementations where (sub) nested classes might be used.
Solution 2: Assure that "friendship bestowed to a nested class is
transitively available only to its own nested classes by similar
declaration within".

To anyone who might say this represents too much special handling in
the rules, I say that it is exactly what is being offerred in the DR
45 proposal, but in silent fashion with no irrevocation. Where
ambiguity or alternative perceptions exists, explicit and declaratve
mannerisms always triumph over the silence of inference in an
axiomatic way.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: francis.glassborow@btinternet.com (Francis Glassborow)
Date: Thu, 30 Aug 2007 13:52:00 GMT
Raw View
Rick Wheeler wrote:
> Granting nested classes unrestricted access to their surrounding class
> in a gratituitous and non-declarative manner does in fact seem
> excessive to me. Most reasoning follows the observation that nested
> classes are members and thus entitled to it. However, membership is
> not a universal monolith, and distinctions already exist between
> member definitions vs dereferenceable elements. Thus there is no
> definitive reason to expect such entitlement. Moreover, bulldozing
> properties of membership into a flat landscape is neither elegant nor
> beneficial to the evolution of the language. The best approach
> continues to be the use and refinement of explicit constructs already
> available through the "friend" relationship. There seem to be two
> esoteric impediments in this regard.
>
> Problem 1: As members, nested classes are not candidates for
> firendship.
> Solution 1: Assure that "nested classes" is included in the list of
> candidates.

Yes, certainly was a possibility
>
> Problem 2: Friendship is not transitive, so nested classes are limited
> in their own implementations where (sub) nested classes might be used.
> Solution 2: Assure that "friendship bestowed to a nested class is
> transitively available only to its own nested classes by similar
> declaration within".

IOWs provide a special case. Special cases almost always result from a
design flaw and we try to avoid them like the plague.


>
> To anyone who might say this represents too much special handling in
> the rules, I say that it is exactly what is being offerred in the DR
> 45 proposal, but in silent fashion with no irrevocation. Where
> ambiguity or alternative perceptions exists, explicit and declaratve
> mannerisms always triumph over the silence of inference in an
> axiomatic way.

The onus is on you to demonstrate how the response to DR45 (which is now
written into the Standard (the current one, not a future one) is
problematical. In a room of over three dozen C++ Standards experts the
vote for the change was almost unanimous (IIRC there were two dissenting
voices)

In addition that part of the Standard involves such things as name
lookup and experience has taught us to avoid tampering with it if
possible. Your proposal above would require us to rework that part of
the Standard yet again. Just accept that it is not going to happen, we
have far more important things to do (and we are, in general quite happy
with what we did in response to DR45 so it would need a very serious
problem to cause us to re-examine it)

>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]
>


--
Note that robinton.demon.co.uk addresses are no longer valid.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Rick Wheeler <rwheeler@oyogeospace.com>
Date: Thu, 30 Aug 2007 14:47:13 CST
Raw View
On Aug 30, 8:52 am, francis.glassbo...@btinternet.com (Francis
Glassborow) wrote:
> Rick Wheeler wrote:
>
> > Solution 2: Assure that "friendship bestowed to a nested classi s
> > transitively available only to its own nested classes by similar
> > declaration within".
>
> IOWs provide a special case. Special cases almost always result from a
> design flaw and we try to avoid them like the plague.

Your statement is correct on all fronts. Yes it is a special case,
although not the first nor (I suspect) the last. It occurs within a
well defined context and whenver there is a special case, that's the
best kind to have. And yes it does result from a design flaw (which
I'll point out as I see it). Furthermore, when two very different
approaches (access vs. no access) can be reasonably justified in
principle, it usually indicates that the flaw is where neither side is
looking.

THE FLAW:
The language provides no constructs for a class to gain control over
access within its boundaries.

As a class defines its universe after the opening curly brace, it has
explicit declarative control over access available to the outside
world, both laterally and derivably. Further control over derivability
has even been added in some quarters using a "sealed" keyword. No such
control exists within. For a long while, most practitioners inferred
(that's bad) that if a new definition was declared in the private/
protected/public areas, then access (both inside and out) followed
suit. Thus, the friend mannerism has been used as a pseudo-explicit
control.

> The onus is on you to demonstrate how the response to DR45 (which is now
> written into the Standard (the current one, not a future one) is
> problematical.

I think I can get around the new behavior. Designs relying on the old
ways can regain propriety (at the expense of complexity) by
proliferating classes into upper namespaces, using forward references,
and adding intervening classes. However, the lack of elegance is
apparent. My biggest beef is the removal of some semblance of
declarative control. The "flattenned landscape" solution seems to be
in contrast to words attributed to Bjarne Stroustrup about the history
of C++ from C wherein "... it does not attempt to remedy problems by
removing features".

>  In a room of over three dozen C++ Standards experts the
> vote for the change was almost unanimous (IIRC there were two dissenting
> voices)

That would truly be intimidating, but I would stand in such
humiliation if it furthered the language. Am I not doing that now?
Please give my regards to the two.

> ... Just accept that it is not going to happen, we
> have far more important things to do (and we are, in general quite happy
> with what we did in response to DR45 so it would need a very serious
> problem to cause us to re-examine it)

I in no way want to interrupt such good work. Perhaps the Committee
could see fit to tackle the fundamental flaw as a part of that
important effort.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Francis Glassborow <francis.glassborow@btinternet.com>
Date: Fri, 31 Aug 2007 09:55:56 CST
Raw View
Rick Wheeler wrote:
>
>> The onus is on you to demonstrate how the response to DR45 (which is now
>> written into the Standard (the current one, not a future one) is
>> problematical.
>
> I think I can get around the new behavior. Designs relying on the old
> ways can regain propriety (at the expense of complexity) by
> proliferating classes into upper namespaces, using forward references,
> and adding intervening classes. However, the lack of elegance is
> apparent. My biggest beef is the removal of some semblance of
> declarative control. The "flattenned landscape" solution seems to be
> in contrast to words attributed to Bjarne Stroustrup about the history
> of C++ from C wherein "... it does not attempt to remedy problems by
> removing features".
>
If there is some reason that you wish to deny a nested class access to
some part of the data of the enclosing class (a use case would greatly
strengthen your argument) then the use of multiple nested classes will
meet your need:

class weird {
    struct part1{
       // whatever
    };
    struct part2 {
        // whatever else
    };
// rest of class definition
};

part1 and part2 have no special access to each other and so cannot
access each other's non-public interfaces.

BTW the original problem almost certainly occurred changed the effect of
declaring a user defined type in a scope. In C such declarations are
always exported to the global scope and so a 'nested' struct definitions
in C are not actually nested, and so are not members of the type.

Making such declarations second class members in C++ (i.e. without full
membership status) was almost certainly accidental.

> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]
>


--
Note that robinton.demon.co.uk addresses are no longer valid.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: bjarne <bjarne@gmail.com>
Date: Sat, 1 Sep 2007 15:40:41 CST
Raw View
On Aug 31, 10:55 am, Francis Glassborow
<francis.glassbo...@btinternet.com> wrote:

> BTW the original problem almost certainly occurred changed the effect of
> declaring a user defined type in a scope. In C such declarations are
> always exported to the global scope and so a 'nested' struct definitions
> in C are not actually nested, and so are not members of the type.
>
> Making such declarations second class members in C++ (i.e. without full
> membership status) was almost certainly accidental.

The decision may have been a mistake (and it may not have been).
However, it was not an accident. Nor would I use the  pejorative
"second class members" to describe the rule.

I do not consider it obvious that a member function of a member class
can access the members of the enclosing class, nor that a member
function of a member class of a member class can access the members of
the enclosing class' enclosing class. How about member functions of a
local class of a member class? Which are the correct answers in
practical use is non-trivial. It was harder still to determine 20
years ago.

The break from the C "non-nested struct" rule wasn't taken lightly and
the implications of various alternative access rules were considered.

   -- Bjarne Stroustrup; http://www.research.att.com/~bs


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Greg Herlihy <greghe@pacbell.net>
Date: Sun, 2 Sep 2007 02:39:06 CST
Raw View
On Aug 30, 1:47 pm, Rick Wheeler <rwhee...@oyogeospace.com> wrote:
> On Aug 30, 8:52 am, francis.glassbo...@btinternet.com (Francis
> Glassborow) wrote:
>> Rick Wheeler wrote:
>>
>>> Solution 2: Assure that "friendship bestowed to a nested classi s
>>> transitively available only to its own nested classes by similar
>>> declaration within".
>>
>> IOWs provide a special case. Special cases almost always result from a
>> design flaw and we try to avoid them like the plague.
>
> Your statement is correct on all fronts. Yes it is a special case,
> although not the first nor (I suspect) the last. It occurs within a
> well defined context and whenver there is a special case, that's the
> best kind to have. And yes it does result from a design flaw (which
> I'll point out as I see it). Furthermore, when two very different
> approaches (access vs. no access) can be reasonably justified in
> principle, it usually indicates that the flaw is where neither side is
> looking.
>
> THE FLAW:
> The language provides no constructs for a class to gain control over
> access within its boundaries.

The lack of access controls within a C++ class is not a flaw in the
language. On the contrary, the fact that a C++ class is not allowed to
wall off portions of itself against itself - simply makes sense for
any number of reasons. For one, the lack of internal class barriers
serves to encourage coherent class design. In particular, any class
design that that called for access controls within its implementation
would be jumble - mixing client and implementation code in a
hodgepodge of ambiguous routines.  The C++ solution for avoiding this
kind of mess is - not to employ language constructs to divvy up the
implementation of the class into ever smaller fiefdoms - but rather to
break apart the problematic class into several, individually-coherent
classes - and have each of these new classes interact, as needed, with
the others as their client.

In a broader sense, access controls regulate how two sets of code
designed apart can interact with each other in a well-defined manner.
Therefore access controls should not be needed whenever both sets of
code embody a single design. And the implementation of a class in C++
(including all of its nested classes) is necessarily the
implementation of a single design because C++ does not allow a class
to be "reopened". In other words, there is no language support for
some other party to add to that class, their own class members.

The question here, as I see it, is not so much a C++ language design
issue (how finely-grained should access control be in C++) as it is a C
++ class design issue (how tightly should a class be defined in C++).
Because no matter the amount of code that C++ programmer might be able
to exclude from a class's implementation - there must remain some
amount of essential code still "inside" of the class (and that is
responsible for the class's implementation) when the design of the
class is complete. And in fact, the boundary of a C++ class is usually
drawn around whatever code would remain "inside" of the class - once
all other code that would not contribute to the class's implementation
- had been left out.

>> The onus is on you to demonstrate how the response to DR45 (which is now
>> written into the Standard (the current one, not a future one) is
>> problematical.
>
> I think I can get around the new behavior. Designs relying on the old
> ways can regain propriety (at the expense of complexity) by
> proliferating classes into upper namespaces, using forward references,
> and adding intervening classes. However, the lack of elegance is
> apparent. My biggest beef is the removal of some semblance of
> declarative control. The "flattenned landscape" solution seems to be
> in contrast to words attributed to Bjarne Stroustrup about the history
> of C++ from C wherein "... it does not attempt to remedy problems by
> removing features".

On the contrary, DR 45 is a very elegant fix: it simply takes C++'s
easily understood distinction between a class's clients and a classes
implementation - and applies it recursively to class's nested classes.
So a nested class, being defined "inside" of its enclosing class (and
is therefore part of its enclosing class's implementation) may access
the enclosing class' private data. In marked contrast, the enclosing
class, being defined "outside" of the nested class, is actually a
client of the nested class. For this reason, an enclosing class may
access only the public members of its nested class (unless the nested
class declares its enclosing class its friend). With DR 45, the the
distinction between a class' clients and its implementation has been
extended in a regular, logical and elegant manner.

Furthermore, DR 45 removes no feature from the language (it merely
lifts a pointless restriction), and its material effect upon any
aspect of the C++ language ranges from the minimal to the nonexistent.
No C++ program has been broken by this change, no C++ code now fails
because it "relied" on the existence of these (now-lifted) access
restrictions - in fact no C++ code behaves any differently then it did
before DR 45 was approved. Similarly, no "workarounds" need to be
implemented in code, nor do any C++ programming practices have to
changed at all. After all, if a C++ programmer does not want a nested
to class to access the private data of its enclosing class, then that
programmer can simply refrain from writing code that does so. There is
nothing in DR 45 that would compel a C++ programmer to write code that
would be in any way at odds with a personal coding philosophy - no
matter what that philosophy might be.

I should also point out that DR 45 provides at least one benefit to
the C++ language: by granting access to its enclosing class's private
members, there is finally a difference between a nested and a non-
nested class vis-   -vis the enclosing class. And as a consequence of
this difference, nested classes in C++ are no longer the useless
language feature that they were, previously.

Greg



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Rick Wheeler <rwheeler@oyogeospace.com>
Date: Mon, 3 Sep 2007 19:05:06 CST
Raw View
On Sep 2, 3:39 am, Greg Herlihy <gre...@pacbell.net> wrote:
>
> The lack of access controls within a C++ class is not a flaw in the
> language. On the contrary, the fact that a C++ class is not allowed to
> wall off portions of itself against itself - simply makes sense for
> any number of reasons. For one, the lack of internal class barriers
> serves to encourage coherent class design. In particular, any class
> design that that called for access controls within its implementation
> would be jumble - mixing client and implementation code in a
> hodgepodge of ambiguous routines.  The C++ solution for avoiding this
> kind of mess is - not to employ language constructs to divvy up the
> implementation of the class into ever smaller fiefdoms - but rather to
> break apart the problematic class into several, individually-coherent
> classes - and have each of these new classes interact, as needed, with
> the others as their client.

What you say is useful in supporting the exact opposite of your claim.
It makes sense for any similar number of reasons for such control to
be provided. The fiefdoms to which you refer may be very pertinent and
applicable to a particular design objective and can enormously
simplify the exposure of what a class must divulge in its
implementation. The rather brash assumption that such approaches yield
hodgepodge and ambiguity is near sighted at best, and more likely
completely wrong. Indeed, an element of cohesion is provided that is
not available in the flat-world model. The design may in fact already
be broken up into classes that would meet your approval.

> In a broader sense, access controls regulate how two sets of code
> designed apart can interact with each other in a well-defined manner.
> Therefore access controls should not be needed whenever both sets of
> code embody a single design. And the implementation of a class in C++
> (including all of its nested classes) is necessarily the
> implementation of a single design because C++ does not allow a class
> to be "reopened". In other words, there is no language support for
> some other party to add to that class, their own class members.

Access controls perform exactly the regulatory function you specify.
However, no chain of reasoning from this observation can reach the
conclusion that access control is not needed in the embodiment of a
single design. It might be accurate to say that in very simple
unfaceted designs, such a need is not apparent. The closure of a class
to further definition is also true but orthogonal.

> The question here, as I see it, is not so much a C++ language design
> issue (how finely-grained should access control be in C++) as it is a C
> ++ class design issue (how tightly should a class be defined in C++).
> Because no matter the amount of code that C++ programmer might be able
> to exclude from a class's implementation - there must remain some
> amount of essential code still "inside" of the class (and that is
> responsible for the class's implementation) when the design of the
> class is complete. And in fact, the boundary of a C++ class is usually
> drawn around whatever code would remain "inside" of the class - once
> all other code that would not contribute to the class's implementation
> - had been left out.

I consider the two elements (access control / class design) related
and unopposed. Class design should always be tightly organized and
well thought out as you say (I think). But the operational logistics
you further describe, while generically true, neither confirm nor deny
the utility of access control within. Moreover, it's not an issue of
access granularity in the context we are discussing, it's whether or
not it should exist at all. I say yes -- it can be leveraged by a
design as an agent of simplification to an otherwise verbose and
contrived presentation.

> On the contrary, DR 45 is a very elegant fix: it simply takes C++'s
> easily understood distinction between a class's clients and a classes
> implementation - and applies it recursively to class's nested classes.
> So a nested class, being defined "inside" of its enclosing class (and
> is therefore part of its enclosing class's implementation) may access
> the enclosing class' private data. In marked contrast, the enclosing
> class, being defined "outside" of the nested class, is actually a
> client of the nested class. For this reason, an enclosing class may
> access only the public members of its nested class (unless the nested
> class declares its enclosing class its friend). With DR 45, the the
> distinction between a class' clients and its implementation has been
> extended in a regular, logical and elegant manner.

The lack of elegance I referred to was with respect to the necessary
changes a design will have to undergo in order to regain
effectiveness. However, I'll stay with your interpretation as to the
elegance of the DR 45 "fix". While it performs exactly as you say, I
find no elegance in the new order it reductively defines. A nested
class is defined into existence at the pure pleasure of the
surrounding class (personified) as a vehicle to achieve and organize
certain functionality. Only amidst the most monotonic assumptions
could unfettered access to the defining class be either desired or
called for. It is the adoption of this unobvious philosophy, yielding
a "flat-earth" interior, that is unappealing. In this new world, a
class is still well represented at the lowest atomic level. But at a
molecular level, broader and separate organization that could be
identified and encapsulated in a surrounding class is ignored. And in
likewise recursion, even more superlative properties captured by
classes at a materials level are lost. In summary, cases will be
encountered more often where a class can no longer singularly
implement a design. Rather, its components (uninteresting outside the
class) will have to be exposed and stitched together in higher scopes
that contribute nothing to the tools of organization other than a
namespace.

> Furthermore, DR 45 removes no feature from the language (it merely
> lifts a pointless restriction), and its material effect upon any
> aspect of the C++ language ranges from the minimal to the nonexistent.

That's not really true. The "no special access" convention was (by me)
well understood and utilized. Also, as limited as it may have been,
the placement of definitions in the private and public areas gave a
modicum of declarative control over interior access. And where public
exposure of the surrounding class was too ill-advised for the benefit
of a single component class, the longstanding "friend" endowment gave
a way out, even though it further identified the need for more
explicit means. While the claim of a "pointless restriction" is
colorful, I don't accept that view in any respect (as you suspect),
except as adding demonstrative exaggeration to your opinion.

> No C++ program has been broken by this change, no C++ code now fails
> because it "relied" on the existence of these (now-lifted) access
> restrictions - in fact no C++ code behaves any differently then it did
> before DR 45 was approved.

So it would seem. However, it is temporary at best. All code base that
in any way utilized these restrictions (by design or accident) will in
fact be at significant risk to changes! Where the compiler once
provided error guidance in attempts at inappropriate access, it will
now be silently cooperative. Moreover, designs providing their own
flat-interior model to a class in a proper declarative way using
friend, will need sanction in one of those pesky "special cases" that
allow the (now abandoned) meaningless declaration.

> Similarly, no "workarounds" need to be
> implemented in code, nor do any C++ programming practices have to
> changed at all.

Unfortunately, that is so not the case. All designs leveraging
compiler assistance (as above) will have to be outwardly unfolded and
refactored to reacquire that previous guardianship being discarded in
the DR 45 change. This will require reopening the design, recapturing
the surrounding knowledge base, and revalidating the new claimed
solution. The process itself will be prone to errors, and generally
unproductive.

> After all, if a C++ programmer does not want a nested
> to class to access the private data of its enclosing class, then that
> programmer can simply refrain from writing code that does so. There is
> nothing in DR 45 that would compel a C++ programmer to write code that
> would be in any way at odds with a personal coding philosophy - no
> matter what that philosophy might be.

There's no merit here. By that logic, we should all use struct and
simply rely on the programmers good behavior and thorough
understanding and inability to make errors.

> I should also point out that DR 45 provides at least one benefit to
> the C++ language: by granting access to its enclosing class's private
> members, there is finally a difference between a nested and a non-
> nested class vis-   -vis the enclosing class. And as a consequence of
> this difference, nested classes in C++ are no longer the useless
> language feature that they were, previously.

C++ nested classes have never been a "useless language feature". Even
as literary exaggeration, that statement has no footing. I would
counter that the subtle distinction that excites you in the new DR 45
is what is really useless. Dare I say that little or nothing is
offered to the designer for the future in this change. A much more
exciting subtle distinction would be the possibility of transitive
friendship in nested classes (under declarative control, of course) in
the alternative I offered earlier. But ecstatically exciting would be
a simple construct of explicit interior access control for all
classes. Important elements seem to be eroded here. The prevalence and
popularity of C++ is due (by far I believe) to the power provided to
its practitioners. This power comes from a dual competency in machine
efficiency and a flexible (yet validated) means of abstraction.  The
DR 45 seems to prefer an academic simplification (by no means
definitively obvious or intrinsic) over pragmatic utility. Almost all
of what it dictates is provided in the existing language (via friend),
and its entire net effect is achieved with the notion of unique nested
transitivity. The difference is whether or not such behavior remains
in the hands of the practitioner where it has been (and should be). As
it stands, this change clearly undermines the practitioner by
diminishing the tools available.

Here is an example case as requested. Chosen names try to mimic some
form of problem statement and while they are likely too contrived,
they serve only to demonstrate.

  class Supervisor
  {
    struct SafetyLock { void set(); void unset(); };
    struct HighVoltagePanel { void connect(); }
    struct Worker
    {
      Supervisor& mentor;
      Worker(Supervisor& _mentor) : mentor(_mentor) { }
      void addWire()
      {
        mentor.addWireSafely();
        delete this;
      }
    };
    SafetyLock  lockOut;
    HighVoltagePanel  panel;
  public:
    Supervisor();
    void addWireSafely()
    {
      lockOut.set();
      panel.connect();
      lockOut.unset();
    }
    void addElectricService() // Needs 2 wires
    {
      new Worker(*this)->addWire();
      new Worker(*this)->addWire();
    }
  };

The Worker cannot access the lockOut or panel directly nor does it
contain any understanding of such elements. It must use the mentorship
of its Supervisor to complete its duty. Any other access attempted
through the Worker is appropriately chastised by the compiler. In a
flat-interior, such access is acceptable, and future additions may see
it as a viable (yet uninformed) shortcut. Thus the design is readily
breached. When implemented in further form using means of multi-
threading the problem is more tangible, where resources must be
managed in similarity to the lockOut. Notice that the addWireSafely is
not appropriate for outside consumers. However, it must be publicly
exposed to make it available to the Worker, as no other interior
access exists. The design can certainly be unfolded into the
surrounding namespace, but is decidedly less clear and contained.
Plus, the exposed nature of previously private elements conjures up
further potential misuse.

As should be quite evident, both perspectives are rooted in sound
principle. However, the DR 45 solution is less functional than what
already existed and what could have been achieved with further
refinement and invention. Both define a consistent set of physics
available for design, but the preferred solution is inarguably the one
that invests more capability in the hands of authors.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: francis.glassborow@btinternet.com (Francis Glassborow)
Date: Tue, 4 Sep 2007 20:28:44 GMT
Raw View
Greg Herlihy wrote:
> I should also point out that DR 45 provides at least one benefit to the=
 C++
> language: by granting access to its enclosing class's private members, =
there
> is finally a difference between a nested and a non-nested class vis-=E0=
-vis
> the enclosing class. And as a consequence of this difference, nested cl=
asses
> in C++ are no longer the useless language feature that they used to be.
>=20
> Greg
>=20
>=20
>=20
It seems you sent a duplicate :-( However I want to add something so I=20
am grabbing the opportunity.

Until DR45 resolution all scopes other than class scope behaved in a=20
uniform manner, a class defined in a scope had access to data etc. also=20
declared/defined in that scope or any enclosing scope. Surely that is=20
perfectly reasonable. However this consistency was broken in the case of=20
nested classes. The resolution of DR45 restored consistency so that the=20
programmer no longer need be concerned about the type of scope in which=20
he is defining/implementing a class, the class instances will have=20
access to everything in the enclosing scope(s).

If a programmer wishes to isolate data/functionality s/he places it in a=20
class as a private member. That now applies in all scopes, including=20
class scope. In the rare case that I want to protect data from a nested=20
class touching it (seems strange as that, to me, implies that the nested=20
class is not properly a member -- i.e. it suggests that there is a=20
design flaw in the class) they do exactly the same thing as they would=20
have done anywhere else, encapsulate the data in a class.

There is simply no need for the old form where nested classes were, by=20
default, denied access to anything that was not public in the enclosing=20
class.

I am sure that Bjarne Stroustrup is correct in his assertion that the=20
original was a considered decision when true nested (and local) classes=20
were introduced into C++ but over the years we have learned a great deal=20
and what seemed like a a sensible conservative position (change as=20
little as possible) showed up as having a flaw. The killer argument was=20
when we realised that the lack of transitivity of friendship (entirely=20
correct that this should be so) meant that enclosing classes needed to=20
know far too much about their implementation, in particular the=20
implementation details of any nested classes.

In summary, post DR45 a class designer who wishes to isolate some aspect=20
of a class from use by a nested class can do so by enclosing the aspect=20
in another nested class (which can grant friendship to the enclosing=20
class). This is the rare case and so it makes sense that the class=20
designer/implementer has to go the extra distance.


--=20
Note that robinton.demon.co.uk addresses are no longer valid.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Rick Wheeler <rwheeler@oyogeospace.com>
Date: Wed, 5 Sep 2007 15:54:33 CST
Raw View
Of the two methods identified earlier for adapting to the DR 45 change
-- 1) projecting nested classes into higher scopes (plus forward
references), and 2) using intervening classes -- I should have given
the latter more consideration. In your apt portrayal of a formative
intervening class, I see several other properties that make this
approach very appealing. First, it embodies the normal construct to
gain declarative control over access within a scope (the surrounding
class in this case). Secondly, it is fully explicit and requires no
added inference (i.e. locale of declaration) to identify the items it
intends to privately coalesce. And lastly, it adds little complexity
to the implementation. While it may still be unclear to you why such
means might be used (or if they're well-formed), I can only say I do
find utility for design areas not intrinsically represented by the
language (e.g. multi-threading). This approach seems quite amenable
for future efforts. However, designs levaraging the previous rules
will still have to be reformed in this manner if it's important to
reestablish previous access models.

Not really discussed is the new available access to previously
protected elements inherited through base classes. I personally have
not exploited this guardianship, but others may have. Those designs
will likely have to follow the first method of refactoring, where
previously nested classes become peer level with no such access. This
will certainly be a more risky process wherever it may be required.

While some commentary clearly shows this change was underestimated in
its effect, I can now agree that there are viable options and means of
navigation available to the designer under the new rules. This
discussion (for me at least) was worthwhile.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]