Topic: friends and local classes


Author: ti953017@rzcipa01.rz.tu-bs.de (Andreas Rossberg)
Date: 8 Feb 1995 11:01:11 GMT
Raw View
In article <3gt6ge$q3m@hpsystem1.informatik.tu-muenchen.de>,
Ulf Schuenemann <schuenem@Informatik.TU-Muenchen.DE> wrote:
>
>class C {
> // we will look at usage of these 3 private members of C
> class N0 {
>  static int classvar;
>  int  instvar;
> public:   N0 () {}
> };
>
> [...]
>
> struct N1 {
>  // interestingly, gcc allows the usage of memberclass N0
>  // insinde N1 although it's private to C (*) (**)

    Yes, actually _all_ of the below code is illegal.

>  N0  * n0p;
>  static void f(N0 & n0)
>  { N0 my_n0; // OK: public member of C::N0
>   N0::classvar++; // ERROR: private member of C::N0
>   n0.classvar++; // ERROR: private member of C::N0
>   n0.instvar++; // ERROR: private member of C::N0
>  }
>  // currently: N1 may not use membervariables of C::
>  // because they are private (*)
>  static void g(C&c)
>  { C::classvar++; // ERROR (*)
>   c.classvar++; // ERROR (*)
>   c.instvar++; // ERROR (*)
>  }
> };
> ...
>};
>
>(*) The idea is to clearly allow all members (including memberclasses)
>of a class the usage of all other (including private) members of that class.
>


Please note that `access' is not something involving just functions.
Access rules apply uniformingly to all _names_ -- not to objects. And any
declaration, for example, can access names, not just the code of functions.

So, when talking about access granted to a nested class, this applies not
only to member functions but to the class as a whole.

Another example I already pointed out in my original posting:

 class A
 {
  typedef int T;
  enum { e = 10 };

  class B
  {
   T t;  // currently illegal
   int a[e]; // currently illegal
  };
 };

No functions or objects involved here.

Also note that this is not just an academical discussion. In my experience,
cases like this appear rather frequently if you make serious use of the
structured concept of nested classes.


 - Andreas Rossberg


PS: To make the current rules consequent, wouldn't it be necessary to
    disallow B to access its own name since it's private to A?  :-)




Author: schuenem@Informatik.TU-Muenchen.DE (Ulf Schuenemann)
Date: 3 Feb 1995 12:10:54 GMT
Raw View
In article <D3DF84.o8@cwi.nl>, olaf@cwi.nl (Olaf Weber) writes:
[..]
|> I think you misunderstood.  What Ulf means is that after
|>
|>  class C {
|>   class N0 { ... };
|>   class N1 { ... };
|>   ...
|>  };
|>
|> the members of C::N0 and C::N1 would have access to all members of C.
|> He did not mean that the private parts of C::N0 should be accessible
|> to C::N1 or vice versa.

Exactly.

|> This seems much more reasonable to me than the current situation.

To give a long example:

class C {
 // we will look at usage of these 3 private members of C
 class N0 {
  static int classvar;
  int  instvar;
 public:   N0 () {}
 };
 static int classvar;
 int  instvar;

 // it's clear what members of C memberfunctions of C may access
 // (all ot them):
 static void f(N0 & n0)
 { N0 my_n0; // OK: public member of C::N0
  N0::classvar++; // ERROR: private member of C::N0
  n0.classvar++; // ERROR: private member of C::N0
  n0.instvar++; // ERROR: private member of C::N0
 }
 static void g(C&c)
 { C::classvar++;
  c.classvar++;
  c.instvar++;
 }

 // compare that to what members of C a memberclass of C may access:
 struct N1 {
  // interestingly, gcc allows the usage of memberclass N0
  // insinde N1 although it's private to C (*) (**)
  N0  * n0p;
  static void f(N0 & n0)
  { N0 my_n0; // OK: public member of C::N0
   N0::classvar++; // ERROR: private member of C::N0
   n0.classvar++; // ERROR: private member of C::N0
   n0.instvar++; // ERROR: private member of C::N0
  }
  // currently: N1 may not use membervariables of C::
  // because they are private (*)
  static void g(C&c)
  { C::classvar++; // ERROR (*)
   c.classvar++; // ERROR (*)
   c.instvar++; // ERROR (*)
  }
 };
 ...
};

(*) The idea is to clearly allow all members (including memberclasses)
of a class the usage of all other (including private) members of that class.

[ (**) I wonder if this an oversight (bug) of gcc ]


Ulf Schuenemann

--------------------------------------------------------------------
Ulf Sch   nemann
Institut f   r Informatik, Technische Universit   t M   nchen.
email: schuenem@informatik.tu-muenchen.de




Author: jason@cygnus.com (Jason Merrill)
Date: Fri, 3 Feb 1995 21:18:21 GMT
Raw View
>>>>> Ulf Schuenemann <schuenem@Informatik.TU-Muenchen.DE> writes:

>   // interestingly, gcc allows the usage of memberclass N0
>   // insinde N1 although it's private to C (*) (**)

> [ (**) I wonder if this an oversight (bug) of gcc ]

Implementing access control for member types is just about on the bottom of
my list of priorities.

Jason




Author: schuenem@Informatik.TU-Muenchen.DE (Ulf Schuenemann)
Date: 31 Jan 1995 18:24:06 GMT
Raw View


ti953017@rzcipa01.rz.tu-bs.de (Andreas Rossberg):
> By default, the nested class B has no access to private members of the outer
> one. To me, this seems illogical, because B clearly is some kind of member of
> A after all.

> I still think a nested class should have private access by default.

tseaver@sam.neosoft.com (Tres Seaver):
> IMNSHO, the committee would do well to "orthagonalize" the concept of
> scope as far as possible;  it is too late, for this iteration, but the
> "principle of least surprise" is or should be of fairly high priority.


IMHO, for the sake of othogonality one should regard everything
(including nested classes) inside a class as a member of that class.
By definition a member has the _permission_ to access private members
of what it is member of. This would not only go for memberfunctions
but also for membertypes (ie nested classes), respectively its memberfunctions.

The _way_ of accessing private members depends on its storage-type:

(a) E.g. it's the case now that static memberfunctions can access
private static members (variables, functions, types).
And they can access private members of an instance iff one is given.

(b) The extension of this would be:
A nested class (respectively its memberfunctions) could access
private static members of the surrounding class.
And it could access private members of an instance of the
surrounding class iff one instance of it is given.

(c) And applied to functions:
A class (respectively its memberfunctions) inside a function could access
static members of the function: static variables, local types.
[ In C/C++ there is notation for an instance of a function ]


Ulf Schuenemann

--------------------------------------------------------------------
Ulf Sch   nemann
Institut f   r Informatik, Technische Universit   t M   nchen.
email: schuenem@informatik.tu-muenchen.de




Author: Doug Judd <djudd@ads.com>
Date: 2 Feb 1995 01:04:55 GMT
Raw View
schuenem@Informatik.TU-Muenchen.DE (Ulf Schuenemann) wrote:
>
> [...]
>
> IMHO, for the sake of othogonality one should regard everything
> (including nested classes) inside a class as a member of that class.
> By definition a member has the _permission_ to access private members
> of what it is member of. This would not only go for memberfunctions
> but also for membertypes (ie nested classes), respectively its memberfunctions.
>
> [...]

I disagree.  Take for example, an automobile engine class that
defines a carburetor class and battery class.   Should the
carburetor know about the battery?  When I go in to buy a new
carburetor, should I tell the clerk what type of battery I have?

I think not.

IMO, a well designed engineering application should be made up of
relatively independent, easily replaceable components with
well-defined interfaces.  Once class B needs to know about the
internal workings of class A (even if B is defined within A),
I feel that it is time to redefine A and B as a single class.

- Doug

 o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o
 Doug Judd
 Advanced Decision Systems (Booz-Allen & Hamilton, Inc.)
 1500 Plymouth St., Mountain View, CA 94043-1230
 djudd@ads.com, (415) 960-7450








Author: jason@cygnus.com (Jason Merrill)
Date: Thu, 2 Feb 1995 09:10:35 GMT
Raw View
>>>>> Shawn Willden <swillden@fcom.cc.utah.edu> writes:

> : I expect that just after GNU pascal comes out G++ will support local
> : functions ... Jason? :)

> I believe GCC (and G++) supports nested functions now.

gcc, yes.  g++, not yet.

Jason




Author: jason@cygnus.com (Jason Merrill)
Date: Thu, 2 Feb 1995 09:13:57 GMT
Raw View
>>>>> Doug Judd <djudd@ads.com> writes:

> IMO, a well designed engineering application should be made up of
> relatively independent, easily replaceable components with
> well-defined interfaces.  Once class B needs to know about the
> internal workings of class A (even if B is defined within A),
> I feel that it is time to redefine A and B as a single class.

This is an overstatement.  Consider matrices and slices, or strings and
substrings -- in both these cases, the second class is a helper, and has no
real existence independent of the first, but it should be a distinct class.

Jason




Author: swillden@fcom.cc.utah.edu (Shawn Willden)
Date: 1 Feb 1995 14:40:41 GMT
Raw View
Andrew Fitzgibbon (andrewfg@dai.ed.ac.uk) wrote:
: swillden@fcom.cc.utah.edu (Shawn Willden) wrote:
: That's not a local function.  It doesn't have lexically scoped access to
: the surrounding function's variables.  It is as hard to implement this
: properly as it is to implement proper local functions.

Yes, I understand that.  In my post I distinguished between `local' and
`nested' functions, the latter having access to the enclosing scope.

: I expect that just after GNU pascal comes out G++ will support local
: functions ... Jason? :)

I believe GCC (and G++) supports nested functions now.

: A.

: --
: Andrew Fitzgibbon (Research Associate),                     andrewfg@ed.ac.uk
: Artificial Intelligence, Edinburgh University.               +44 031 650 4504
:                         http://www.dai.ed.ac.uk/staff/personal_pages/andrewfg
:        "If it ain't broke, don't fix it" - traditional (c1950)
:           "A stitch in time saves nine." - traditional (c1590)

--
Shawn Willden
swillden@icarus.weber.edu




Author: swillden@fcom.cc.utah.edu (Shawn Willden)
Date: 1 Feb 1995 14:42:21 GMT
Raw View
Fergus Henderson (fjh@munta.cs.mu.OZ.AU) wrote:
: swillden@fcom.cc.utah.edu (Shawn Willden) wrote:
: >>
: >> Just make a local class with a static function if you need a local function.
: >>
: >> void functionWithLocalFunction() {
: >>     struct Local {
: >>  int static compare(const void* a, const void* b) { ... };
: >>     };
: >>
: >>     //...
: >>     qsort(array, sizeof(array)/sizeof(array[0]), sizeof(array),
: >>           &Local::compare);
: >>     }

: If it's that easy, why can't the compiler do it automatically?

I agree it would be nicer if local functions were a part of the
language.  Even better if they were true local functions that
had access to the enclosing scope's variables.

: --
: Fergus Henderson - fjh@munta.cs.mu.oz.au
: all [L] (programming_language(L), L \= "Mercury") => better("Mercury", L) ;-)

--
Shawn Willden
swillden@icarus.weber.edu




Author: olaf@cwi.nl (Olaf Weber)
Date: Thu, 2 Feb 1995 11:43:20 GMT
Raw View
In article <3gpb3n$nh4@booz.bah.com>, Doug Judd <djudd@ads.com> writes:
> schuenem@Informatik.TU-Muenchen.DE (Ulf Schuenemann) wrote:

>> IMHO, for the sake of othogonality one should regard everything
>> (including nested classes) inside a class as a member of that
>> class.  By definition a member has the _permission_ to access
>> private members of what it is member of. This would not only go for
>> memberfunctions but also for membertypes (ie nested classes),
>> respectively its memberfunctions.

> I disagree.  Take for example, an automobile engine class that
> defines a carburetor class and battery class.   Should the
> carburetor know about the battery?  When I go in to buy a new
> carburetor, should I tell the clerk what type of battery I have?

> I think not.

I think you misunderstood.  What Ulf means is that after

 class C {
  class N0 { ... };
  class N1 { ... };
  ...
 };

the members of C::N0 and C::N1 would have access to all members of C.
He did not mean that the private parts of C::N0 should be accessible
to C::N1 or vice versa.

This seems much more reasonable to me than the current situation.

-- Olaf Weber




Author: jason@cygnus.com (Jason Merrill)
Date: Wed, 25 Jan 1995 20:21:50 GMT
Raw View
>>>>> Viktor Yurkovsky <n4mation@panix.com> writes:

> swillden@fcom.cc.utah.edu (Shawn Willden) wrote:

>> Just make a local class with a static function if you need a local function.
>>
>> void functionWithLocalFunction()
>> {
>> struct Local
>> {
>> int static compare(const void* a, const void* b)
>> {
>> const int *intA = reinterpret_cast<const int*>(a);
>> const int *intB = reinterpret_cast<const int*>(b);
>> if (*intA == *intB)
>> return 0;
>> else if (*intA < *intB)
>> return -1;
>> else
>> return 1;
>> }
>> };
>>
>> //...
>> qsort(array, sizeof(array)/sizeof(array[0]), sizeof(array),
>> &Local::compare);
>> }
>>
>> ...

> Hmm.. This creates a rather large inline, doesn't it?

The compiler is under no obligation to inline calls.  And since the
function is used through a pointer, the compiler would have to be mighty
clever to do so.

Jason




Author: Viktor Yurkovsky <n4mation@panix.com>
Date: 25 Jan 1995 23:07:41 GMT
Raw View
>code deleted
> The compiler is under no obligation to inline calls.  And since the
> function is used through a pointer, the compiler would have to be mighty
> clever to do so.

All very true.





Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Thu, 26 Jan 1995 11:04:13 GMT
Raw View
In article <FENSTER.95Jan24182929@ground.cs.columbia.edu> fenster@ground.cs.columbia.edu (Sam Fenster) writes:
>
>clamage@Eng.Sun.COM (Steve Clamage) writes:
>
>> Who said local classes are a good idea? I think they are pointless.[...]  A
>> number of people on the C++ Committee would like to eliminate member
>> functions from local classes (myself included), although I don't expect that
>> to happen.
>
>Let's say you want to guarantee that some action takes place when a function
>exits, regardless of whether it's by any of a number of return statements,
>falling off the end, or because of an exception.  The only way is to create a
>local object with a destructor that performs the action.  That destructor must
>have the function's local variables in its scope:
>
>     void f () {
>        // ...
>        class On_Exit {~On_Exit() {delete foo; close(bar); baz--;};} on_exit;
>        // ...
>     }
>
>When Bjarne made "int i;" an executable statement so it could be put anywhere
>in a block, his rationale was that things should be declared where they are
>used.  The same goes for a class that is created for a local purpose.  And
>such classes must be allowed to have member functions.
>
>Ideally, we'd have local functions too, for similar reasons (e.g. a comparison
>function to pass to "qsort").  I don't expect that soon.  But let's not get
>rid of local classes, OK?


 If you want a "real" C++ compiler, try Metaware High C/C++.
It not only support nested (local) functions, but has a full
closure type.

 Sigh. In C++ almost everything except functions can be nested.
I consider that a gratuitous omission destroying the orthogonality
of the language. To me it is plain daft to provide full object
orientation and skip over the most basic structured programming
ideas. Structured programming may not be enough, but in
two decades of research and experience we have learned, surely,
that "flat" languages like C and Cobol and Fortran have severe
problems. Now we have C++ which is "flat", but allows you
to break the global "flat" space up into little bits. (objects).

 So we have not learned that localisation and anonymity
are powerful ideas.  All we've done is permit partitioning
the flat space.  And I contend that _that_ is not enough:
within an object, we just have a miniture version of C, Cobol,
or Fortran. Gak.


--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: brettp@mahjongg.rchland.ibm.com (Brett Peterson)
Date: 26 Jan 1995 17:19:28 GMT
Raw View
In article <3g5pn6$16p@news.cc.utah.edu>, swillden@fcom.cc.utah.edu (Shawn Willden) writes:
|> Andreas Rossberg (ti953017@rzcipa01.rz.tu-bs.de) wrote:
|>
|> :  class A
|> :  {
|> :  private:
|> :   class B;
|> :   friend class B;
|> :   class B { /* ... */ };
|> :  };
|>
|> : This is tedious and even used to be illegal.
|>
|> : Why are the rules that way? Could anybody give me a hint? However, IMO, the
|> : language should at least allow the terse notion of
|>
|> :   friend class B { /* ... */ };
|>
[snip]
|> or
|>   friend class B;
|>   class B { /* ... */ };
|>
|> are legal, and closer.
|>

This is not semantically equivalent to what Andreas wrote above. Since "friend class B" introduces
B, then the name B is entered into the same scope as the name of the containing class. Thus,
"friend class B" gives friendship to the global class B and not to the local class B.



Author: andrewfg@dai.ed.ac.uk (Andrew Fitzgibbon)
Date: Fri, 27 Jan 1995 10:26:33 GMT
Raw View
swillden@fcom.cc.utah.edu (Shawn Willden) wrote:
>
> Sam Fenster (fenster@ground.cs.columbia.edu) wrote:
> : Ideally, we'd have local functions too, for similar reasons (e.g. a comparison
> : function to pass to "qsort").  I don't expect that soon.  But let's not get
> : rid of local classes, OK?
>
> Just make a local class with a static function if you need a local function.
> [paraphrasing:]
> void functionWithLocalFunction() {
>     struct Local {
>  int static compare(const void* a, const void* b)
>      {...}
>  };
>     qsort(array, sizeof(array)/sizeof(array[0]), sizeof(array),
>           &Local::compare);

That's not a local function.  It doesn't have lexically scoped access to
the surrounding function's variables.  It is as hard to implement this
properly as it is to implement proper local functions.

I expect that just after GNU pascal comes out G++ will support local
functions ... Jason? :)

A.

--
Andrew Fitzgibbon (Research Associate),                     andrewfg@ed.ac.uk
Artificial Intelligence, Edinburgh University.               +44 031 650 4504
                        http://www.dai.ed.ac.uk/staff/personal_pages/andrewfg
       "If it ain't broke, don't fix it" - traditional (c1950)
          "A stitch in time saves nine." - traditional (c1590)




Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Fri, 27 Jan 1995 14:01:59 GMT
Raw View
swillden@fcom.cc.utah.edu (Shawn Willden) wrote:
>>
>> Just make a local class with a static function if you need a local function.
>>
>> void functionWithLocalFunction() {
>>     struct Local {
>>  int static compare(const void* a, const void* b) { ... };
>>     };
>>
>>     //...
>>     qsort(array, sizeof(array)/sizeof(array[0]), sizeof(array),
>>           &Local::compare);
>>     }

If it's that easy, why can't the compiler do it automatically?

--
Fergus Henderson - fjh@munta.cs.mu.oz.au
all [L] (programming_language(L), L \= "Mercury") => better("Mercury", L) ;-)




Author: jason@cygnus.com (Jason Merrill)
Date: Sat, 28 Jan 1995 02:01:50 GMT
Raw View
>>>>> Andrew Fitzgibbon <andrewfg@dai.ed.ac.uk> writes:

> swillden@fcom.cc.utah.edu (Shawn Willden) wrote:
>>
>> Sam Fenster (fenster@ground.cs.columbia.edu) wrote:
>> : Ideally, we'd have local functions too, for similar reasons (e.g. a comparison
>> : function to pass to "qsort").  I don't expect that soon.  But let's not get
>> : rid of local classes, OK?
>>
>> Just make a local class with a static function if you need a local function.
>> [paraphrasing:]
>> void functionWithLocalFunction() {
>> struct Local {
>> int static compare(const void* a, const void* b)
>> {...}
>> };
>> qsort(array, sizeof(array)/sizeof(array[0]), sizeof(array),
>> &Local::compare);

> That's not a local function.  It doesn't have lexically scoped access to
> the surrounding function's variables.  It is as hard to implement this
> properly as it is to implement proper local functions.

Actually, it does have lexically scoped access to the surrounding
function's variables.  It's just that using an auto variable or a parameter
is ill-formed.

> I expect that just after GNU pascal comes out G++ will support local
> functions ... Jason? :)

Well, GNU C already supports nested functions, so it doesn't need to wait
for GNU pascal.  It just needs to wait for someone to implement it (which
may be happening).

Jason




Author: jgealow@mtl.mit.edu (Jeffrey C. Gealow)
Date: 23 Jan 1995 04:02:21 GMT
Raw View
In article clamage@Eng.Sun.COM (Steve Clamage) writes:

   >jgealow@mtl.mit.edu (Jeffrey C. Gealow) wrote:
   >>
   >> Should a local class assume the friendships of the enclosing function?
   >> For example, consider the following:
   >>
   >> class X {
   >>   int i;
   >>   friend int f(X);
   >> };
   >>
   >> int f(X o)
   >> {
   >>   struct local {
   >>     static int l(X o) { return o.i; }  // error?
   >>   };
   >>   return local::l(o);
   >> }
   >>
   >> Should struct local, declared within the definition of f(X), act
   >> as a friend of class X?

   No function is a friend of a class unless that class so declares
   that function. Since local::l is not declared to be a friend of X,
   it isn't a friend.  (It cannot be so declared because it isn't visible.)

   Friendship is not inherited, isn't implicit, and cannot be asserted.

   See ARM 11.4.

I understand the rationale for the general rule that friendship is not
implicit and accept Steve's interpretation of the ARM.  But it seems
that the rationale, as explained in the ARM, does not apply to the
situation I presented.  Perhaps I'm missing something?  If not, I think
the draft standard should be modified so that a local class assumes
the friendships of the enclosing function.  Note that there is no way
to use a local class outside the enclosing function and that there is
no way to explicitly grant friendship to a local class.  If local
classes are a good idea, why cripple them with rigid access control?

Jeff




Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 23 Jan 1995 16:12:06 GMT
Raw View
jgealow@mtl.mit.edu (Jeffrey C. Gealow) writes:

>In article clamage@Eng.Sun.COM (Steve Clamage) writes:

>   No function is a friend of a class unless that class so declares
>   that function. Since local::l is not declared to be a friend of X,
>   it isn't a friend.  (It cannot be so declared because it isn't visible.)

>   Friendship is not inherited, isn't implicit, and cannot be asserted.

>   See ARM 11.4.

>I understand the rationale for the general rule that friendship is not
>implicit and accept Steve's interpretation of the ARM.  But it seems
>that the rationale, as explained in the ARM, does not apply to the
>situation I presented.  Perhaps I'm missing something?  If not, I think
>the draft standard should be modified so that a local class assumes
>the friendships of the enclosing function.  Note that there is no way
>to use a local class outside the enclosing function and that there is
>no way to explicitly grant friendship to a local class.  If local
>classes are a good idea, why cripple them with rigid access control?

Who said local classes are a good idea? I think they are pointless.
(Local structs/unions (PODs) are sometimes useful, however.)
A number of people on the C++ Committee would like to eliminate
member functions from local classes (myself included), although I
don't expect that to happen.

You can't declare a nested function in C++, but an inline function
in a local class provides a loophole -- for inline member functions
only. The loophole greately complicates compilers, to little or no
good purpose (IMHO).

(I expect John Skaller to jump in here with an example of a program
which cannot be written without full-bore local classes :-) )

With namespaces, C++ has so many different kinds of scopes, both
named and anonymous, that local classes and nested functions seem
unnecessary. Nevertheless, nested functions allow some powerful
programming techniques which are otherwise very inconvient.

Either C++ should have nested functions, or member functions of local
classes should be disallowed. The current set of rules makes no sense
(IMHO).
--
Steve Clamage, stephen.clamage@eng.sun.com




Author: fenster@ground.cs.columbia.edu (Sam Fenster)
Date: 24 Jan 1995 23:29:28 GMT
Raw View
clamage@Eng.Sun.COM (Steve Clamage) writes:

> Who said local classes are a good idea? I think they are pointless.[...]  A
> number of people on the C++ Committee would like to eliminate member
> functions from local classes (myself included), although I don't expect that
> to happen.

Let's say you want to guarantee that some action takes place when a function
exits, regardless of whether it's by any of a number of return statements,
falling off the end, or because of an exception.  The only way is to create a
local object with a destructor that performs the action.  That destructor must
have the function's local variables in its scope:

     void f () {
        // ...
        class On_Exit {~On_Exit() {delete foo; close(bar); baz--;};} on_exit;
        // ...
     }

When Bjarne made "int i;" an executable statement so it could be put anywhere
in a block, his rationale was that things should be declared where they are
used.  The same goes for a class that is created for a local purpose.  And
such classes must be allowed to have member functions.

Ideally, we'd have local functions too, for similar reasons (e.g. a comparison
function to pass to "qsort").  I don't expect that soon.  But let's not get
rid of local classes, OK?




Author: ti953017@rzcipa01.rz.tu-bs.de (Andreas Rossberg)
Date: 24 Jan 1995 13:19:56 GMT
Raw View
A similar but more important issue are nested classes:

 class A
 {
 private:
  typedef int T;
  void f();

  class B
  {
  public:
   T t;    // error
   void g(A &a) { a.f(); }  // error
  };
 };


By default, the nested class B has no access to private members of the outer
one. To me, this seems illogical, because B clearly is some kind of member of
A after all.

It also is a nuisance since such access is frequently needed for private
implementation classes (look at the STL, for example). And the only way to
achieve it is writing

 class A
 {
 private:
  class B;
  friend class B;
  class B { /* ... */ };
 };

This is tedious and even used to be illegal.

Why are the rules that way? Could anybody give me a hint? However, IMO, the
language should at least allow the terse notion of

  friend class B { /* ... */ };


 - Andreas Rossberg




Author: swillden@fcom.cc.utah.edu (Shawn Willden)
Date: 25 Jan 1995 15:11:34 GMT
Raw View
Andreas Rossberg (ti953017@rzcipa01.rz.tu-bs.de) wrote:

:  class A
:  {
:  private:
:   class B;
:   friend class B;
:   class B { /* ... */ };
:  };

: This is tedious and even used to be illegal.

: Why are the rules that way? Could anybody give me a hint? However, IMO, the
: language should at least allow the terse notion of

:   friend class B { /* ... */ };

Well,
  class B { /* ... */ };
  friend B;

or
  friend class B;
  class B { /* ... */ };

are legal, and closer.

Shawn.

--
Shawn Willden
swillden@icarus.weber.edu




Author: swillden@fcom.cc.utah.edu (Shawn Willden)
Date: 25 Jan 1995 15:22:46 GMT
Raw View
Sam Fenster (fenster@ground.cs.columbia.edu) wrote:
: Ideally, we'd have local functions too, for similar reasons (e.g. a comparison
: function to pass to "qsort").  I don't expect that soon.  But let's not get
: rid of local classes, OK?

Just make a local class with a static function if you need a local function.

void functionWithLocalFunction()
    {
    struct Local
 {
 int static compare(const void* a, const void* b)
     {
     const int *intA = reinterpret_cast<const int*>(a);
     const int *intB = reinterpret_cast<const int*>(b);
     if (*intA == *intB)
  return 0;
     else if (*intA < *intB)
  return -1;
     else
  return 1;
     }
 };

    //...
    qsort(array, sizeof(array)/sizeof(array[0]), sizeof(array),
          &Local::compare);
    }

Note that this is not the same as a "nested" function, because
nested functions typically have access to variables declared
in the scope of the nesting function.

Shawn.

--
Shawn Willden
swillden@icarus.weber.edu




Author: Viktor Yurkovsky <n4mation@panix.com>
Date: 25 Jan 1995 15:41:06 GMT
Raw View
swillden@fcom.cc.utah.edu (Shawn Willden) wrote:
>
> Sam Fenster (fenster@ground.cs.columbia.edu) wrote:
> : Ideally, we'd have local functions too, for similar reasons (e.g. a comparison
> : function to pass to "qsort").  I don't expect that soon.  But let's not get
> : rid of local classes, OK?
>
> Just make a local class with a static function if you need a local function.
>
> void functionWithLocalFunction()
>     {
>     struct Local
>  {
>  int static compare(const void* a, const void* b)
>      {
>      const int *intA = reinterpret_cast<const int*>(a);
>      const int *intB = reinterpret_cast<const int*>(b);
>      if (*intA == *intB)
>   return 0;
>      else if (*intA < *intB)
>   return -1;
>      else
>   return 1;
>      }
>  };
>
>     //...
>     qsort(array, sizeof(array)/sizeof(array[0]), sizeof(array),
>           &Local::compare);
>     }
>
>...

Hmm.. This creates a rather large inline, doesn't it?




Author: tseaver@sam.neosoft.com (Tres Seaver)
Date: Wed, 25 Jan 1995 09:49:48
Raw View
In article <3g0kgm$gue@engnews2.Eng.Sun.COM> clamage@Eng.Sun.COM (Steve Clamage) writes:

<snip>

>With namespaces, C++ has so many different kinds of scopes, both
>named and anonymous, that local classes and nested functions seem
>unnecessary. Nevertheless, nested functions allow some powerful
>programming techniques which are otherwise very inconvient.

>Either C++ should have nested functions, or member functions of local
>classes should be disallowed. The current set of rules makes no sense
>(IMHO).
>--
>Steve Clamage, stephen.clamage@eng.sun.com

Bingo!  I have never understood why (except to keep life simple for compiler
writers) nested functions weren't allowed -- as you say, some techniques
require, in the absence of nested functions, a ridiculous amount of work.

IMNSHO, the committee would do well to "orthagonalize" the concept of
scope as far as possible;  it is too late, for this iteration, but the
"principle of least surprise" is or should be of fairly high priority.

I don't think that complicating things for implementers is a sufficient QED
for disallowing the concept;  any compiler writer who wants to keep life
simple had better pick a language without ties to a language with as bizarre a
grammar and syntax as C's!

=========================================================================
 Tres Seaver,               |  tseaver@neosoft.com
 MACRO Enterprises, Inc.,   |  Vox: (713) 827-7273
 Houston, Texas, USA.       |  Fax: (713) 827-7278
=========================================================================




Author: jgealow@mtl.mit.edu (Jeffrey C. Gealow)
Date: 21 Jan 1995 17:35:51 GMT
Raw View
Should a local class assume the friendships of the enclosing function?
For example, consider the following:

class X {
  int i;
  friend int f(X);
};

int f(X o)
{
  struct local {
    static int l(X o) { return o.i; }  // error?
  };
  return local::l(o);
}

Should struct local, declared within the definition of f(X), act
as a friend of class X?

The question doesn't seem to be addressed in the ARM.  Thus, I am
inclined to conclude that under the current draft standard, a local
class does not assume the friendships of the enclosing function.

I suggest that under the final ANSI standard, a local class should
assume the friendships of the enclosing function.  The rationale
for the rule ``Friendship is neither inherited or transitive''
does not seem to apply.

Jeff




Author: Viktor Yurkovsky <n4mation@panix.com>
Date: 21 Jan 1995 19:52:18 GMT
Raw View
jgealow@mtl.mit.edu (Jeffrey C. Gealow) wrote:
>
> Should a local class assume the friendships of the enclosing function?
> For example, consider the following:
>
> class X {
>   int i;
>   friend int f(X);
> };
>
> int f(X o)
> {
>   struct local {
>     static int l(X o) { return o.i; }  // error?
>   };
>   return local::l(o);
> }
>
> Should struct local, declared within the definition of f(X), act
> as a friend of class X?
Seems to me that friend applies to the entire function, and anything
inside that function should have access.  However, there are some
interesting problems stemming from that such as: if this function
now calls a function in another class, does it pass the friendship
factor on?

Is friend dynamically or statically bound, really?

-------------------------------
n4mation@panix.com             |
Data In Formation Inc.         |
                               |
Victor Yurkovsky               |
                               |
Compiler maker                 |
                               |
Special discounts for          |
weddings and funerals.         |
_______________________________|

Enjoy your compile time.  I WILL take it away from you!





Author: graehl@usc.edu (Jonathan Graehl)
Date: 22 Jan 1995 00:34:50 GMT
Raw View
this function
>now calls a function in another class, does it pass the friendship
>factor on?
>
>Is friend dynamically or statically bound, really?

Well, all access rules are checked at compile time, so they would be
statically bound.


Jonathan Graehl




Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 22 Jan 1995 03:47:40 GMT
Raw View
Viktor Yurkovsky <n4mation@panix.com> writes:

>jgealow@mtl.mit.edu (Jeffrey C. Gealow) wrote:
>>
>> Should a local class assume the friendships of the enclosing function?
>> For example, consider the following:
>>
>> class X {
>>   int i;
>>   friend int f(X);
>> };
>>
>> int f(X o)
>> {
>>   struct local {
>>     static int l(X o) { return o.i; }  // error?
>>   };
>>   return local::l(o);
>> }
>>
>> Should struct local, declared within the definition of f(X), act
>> as a friend of class X?
>
>Seems to me that friend applies to the entire function, and anything
>inside that function should have access.

No.

No function is a friend of a class unless that class so declares
that function. Since local::l is not declared to be a friend of X,
it isn't a friend.  (It cannot be so declared because it isn't visible.)

Friendship is not inherited, isn't implicit, and cannot be asserted.

See ARM 11.4.

N.B.: A shorthand notation allows all the member functions of a
class to be simultaneously declared to be friends of another
class. That notation is not used here (and can't be used, because
the class "local" isn't visible).

--
Steve Clamage, stephen.clamage@eng.sun.com




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sun, 22 Jan 1995 19:07:15 GMT
Raw View
In article <3froli$gss@news.panix.com> Viktor Yurkovsky <n4mation@panix.com> writes:
>inside that function should have access.  However, there are some
>interesting problems stemming from that such as: if this function
>now calls a function in another class, does it pass the friendship
>factor on?

 No.
>
>Is friend dynamically or statically bound, really?

 Friendship is statically enforced. However, there is
a difference between static protection (including
friendship) and _dynamic_ accessibility.

 A friend or member, for example, can grant access to the
private details of an object to the public, or a specific
function, by simply passing a pointer to the private member.

 There is only one way to stop this that I know of:
ensure the private member is of a _private type_.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189