Topic: an extension idea that someone else might even like :-)


Author: spitzak@hollywood.cinenet.net (Bill Spitzak)
Date: 3 Sep 1994 18:02:02 -0700
Raw View
jasonoz@cairo.anu.edu.au (Jason Ozolins) writes:
>implementation LongDescriptiveName {

> LongDescriptiveName () {
> .
> <constructor code>
> .
> }
>
>        AMemberFunction (....) {
>        .
> .
> }

> <other function definitions, all of which are member functions
>  of class LongDescriptiveName>
>}

I previously suggested a similar thing, but it introduces no new
keywords because it uses the '...' token.  Didn't get any responses,
however:

foobar.H:

 class foo {
  int x;
  int member1() {code();} // this is inlined
  int member2();
  ... // optional
 };

foobar.C

 #include "foobar.H"

 class foo {
  ... // indicates implementation
  int member2() {morecode();} // this is NOT inlined
  int member3() {more();} // legal and inlined
  ... // you can split it even further
 };

end

It is illegal for "class foo { ..." to be encountered unless there
was a previous "class foo {<stuff>}" encountered.

If the previous "class foo {}" did not end with "..." then the new
one can only implement methods, and declare new non-virtual private
methods (which *are* inlined).

If the previous "class foo {}" did end with a "..." then the new
block can declare anything.  The compiler acts exactly as
though the two blocks were concatenated together.

If the last "class foo {}" encountered ends with "..." then this is a
partially-defined class.  You are only allowed to declare pointers and
references to this class, you cannot call new or sizeof on it.  Once
you have one of these pointers you can access any of the public
members seen in any of the class declaration blocks.

The syntax "class foo {...};" is a *leading* "..." with nothing
after it.  To get the effect of nothing followed by a trailing "..."
use the existing C++ syntax "class foo;"

Bill Spitzak





Author: g2devi@cdf.toronto.edu (Robert N. Deviasse)
Date: Sun, 4 Sep 1994 15:42:44 GMT
Raw View
In article <DAG.94Sep4122404@bellman.control.lth.se>,
Dag Bruck <dag@control.lth.se> wrote:
>>>>>> "J" == Jason Ozolins <jasonoz@cairo.anu.edu.au> writes:
>
>[Most of proposal to avoid repeating e.g. template parameter list deleted.]
>
>J> template <class X> implementation LongClassName {
>J>    LongClassName(LongClassName &src) { .  .  .  }
>J>    AnotherMemberFunction (...)  { .  .  }
>J> }
>
>J> I realise that it is well past the stage where the
>J> standard can be influenced by idle suggestions, but if there is
>J> enough interest in this I might write some kind of preprocessor to
>J> take things written in this style and emit normal, unreadable C++
>J> function definitions.
>
>The strongest drawback of the proposal, as I see it, is that it
>provides convenience but no new functionality.  I think someone said
>that about references, too.
>

It actually does. Currently, it's impossible to write:
     class Class {
        private:
           class Nested { ... };
           Nested fn();
        // ...
     };

     Class::Nested Class::fn() { ... }

because Class::Nested is private. Using the proposal, one could
presumably write:
     implementation class Class {
        Nested fn() { ... }
     };


>In any case, the suggested approach to
>
> 1.  Implement the feature
> 2.  See if people like it
> 3.  Propose it for the next round of standardization
>
>makes sense to me.
>    -- Dag

Agreed.

Implicit in step 1, is defining a specification for the feature and
testing it. As I see it, the current informal specification is open to
several possible interpretations. For instance:
   (1) Should there be only one implementation per class or should
       implementation have a more "class namespace" like property.
       The class namespace approach is more natural to C++, but the
       implementation class approach does have it's advantages. Because
       there is precisely one implementation, one could be able to
       write:

           class Class {
             public:
              static const X=32;
              with implementation;   // noting that there is an implementation
           };

           implementation class Class {};
       and have the compiler implicitly generate the definition:
           implementation class Class { static const X; };
       Because there is only one implementation per class, the compiler
       knows where to place any class implementation specific information
       like vtables, RTTI, and member functions in the class that cannot
       be inlined.

   (2) Can member functions and static members be defined in the
       implementation that are not defined in the class specification
       header? If so, how should they be defined so that the class'
       encapsulation is not broken? Personally, I don't see any reason
       why the contents of the class implementation should be any
       business of the outside world, so that in:
            implementation class Class {
               int something_new_added_to_the_class() { ... }
            };
       something_new_added_to_the_class should not be accessible outside
       the class implementation.

   (3) Can the implementation specify "friend"s? I feel the answer should
       be no since it breaks the encapsulation of the class.

There are likely many other questions and implications that I haven't
yet thought of. I think it's a valuable feature to add to C++, but it'll
take quite a while to iron out all the details.


Take care
    Robert
--
/----------------------------------+------------------------------------------\
| Robert N. Deviasse               |"If we have to re-invent the wheel,       |
| EMAIL: g2devi@cdf.utoronto.ca    |  can we at least make it round this time"|
+----------------------------------+------------------------------------------/




Author: rjl@f111.iassf.easams.com.au (Rohan LENARD)
Date: 5 Sep 1994 07:31:10 +1000
Raw View
In article <CvM3n9.Fqn@cdf.toronto.edu>,
Robert N. Deviasse <g2devi@cdf.toronto.edu> wrote:
  >
  >It actually does. Currently, it's impossible to write:
  >     class Class {
  >        private:
  >           class Nested { ... };
  >           Nested fn();
  >        // ...
  >     };
  >
  >     Class::Nested Class::fn() { ... }
  >
  >because Class::Nested is private. Using the proposal, one could
  >presumably write:
  >     implementation class Class {
  >        Nested fn() { ... }
  >     };

You can write that now.  Sounds like your compiler is broken.  Off course
the function fn() can only be called by another function within class Class.

  >Implicit in step 1, is defining a specification for the feature and
  >testing it. As I see it, the current informal specification is open to
  >several possible interpretations. For instance:
  >   (1) Should there be only one implementation per class or should
  >       implementation have a more "class namespace" like property.
  >       The class namespace approach is more natural to C++, but the
  >       implementation class approach does have it's advantages. Because
  >       there is precisely one implementation, one could be able to
  >       write:
  >
  >           class Class {
  >             public:
  >              static const X=32;
  >              with implementation;   // noting that there is an implementation
  >           };
  >
  >           implementation class Class {};
  >       and have the compiler implicitly generate the definition:
  >           implementation class Class { static const X; };
  >       Because there is only one implementation per class, the compiler
  >       knows where to place any class implementation specific information
  >       like vtables, RTTI, and member functions in the class that cannot
  >       be inlined.

The statement about one implementation is is very naive.  Putting everything
into one translation unit, is a sure fire way of guaranteeing large executables
with slow performance (due to paging).

Additionally, the committee have gone out of their way to allow things to
be split over multiple places. eg a namespace can be split into multiple
parts just be defining it in different spots.
eg. (from Bjarne's great book D&E of C++)

 namespace Mine {
   void f();
        };

        #include <stdio.h>

        namespace Mine {
          int g();
        };

Doing differently for the classes implementation is a gratuitous
un-orthogonality (it's a pity a class declaration can't be split up, but I
think most can see reason behind that).

Regards,
 Rohan
--
----------------------------------------------------------------------------
rjl@iassf.easams.com.au | All quotes can be attributed to my automated quote
Rohan Lenard            | writing tool.  Yours for just $19.95; and if you
+61-2-367-4555          | call now you'll get a free set of steak knives ...




Author: g2devi@cdf.toronto.edu (Robert N. Deviasse)
Date: Mon, 5 Sep 1994 01:50:33 GMT
Raw View
In article <34deau$d4v@f111.iassf.easams.com.au>,
Rohan LENARD <rjl@f111.iassf.easams.com.au> wrote:
>In article <CvM3n9.Fqn@cdf.toronto.edu>,
>Robert N. Deviasse <g2devi@cdf.toronto.edu> wrote:
>  >
>  >It actually does. Currently, it's impossible to write:
>  >     class Class {
>  >        private:
>  >           class Nested { ... };
>  >           Nested fn();
>  >        // ...
>  >     };
>  >
>  >     Class::Nested Class::fn() { ... }
>  >
>  >because Class::Nested is private. Using the proposal, one could
>  >presumably write:
>  >     implementation class Class {
>  >        Nested fn() { ... }
>  >     };
>
>You can write that now.  Sounds like your compiler is broken.  Off course
>the function fn() can only be called by another function within class Class.
>

Hmmm, I recall a year ago that there was a discussion here why it was not
allowed. At the time, my compiler didn't compile it either, although it
does not. I guess that this language rule has changed?

>  >Implicit in step 1, is defining a specification for the feature and
>  >testing it. As I see it, the current informal specification is open to
>  >several possible interpretations. For instance:
>  >   (1) Should there be only one implementation per class or should
>  >       implementation have a more "class namespace" like property.
>  >       The class namespace approach is more natural to C++, but the
>  >       implementation class approach does have it's advantages. Because
>  >       there is precisely one implementation, one could be able to
>  >       write:
>  >
>  >           class Class {
>  >             public:
>  >              static const X=32;
>  >              with implementation;   // noting that there is an implementation
>  >           };
>  >
>  >           implementation class Class {};
>  >       and have the compiler implicitly generate the definition:
>  >           implementation class Class { static const X; };
>  >       Because there is only one implementation per class, the compiler
>  >       knows where to place any class implementation specific information
>  >       like vtables, RTTI, and member functions in the class that cannot
>  >       be inlined.
>
>The statement about one implementation is is very naive.  Putting everything
>into one translation unit, is a sure fire way of guaranteeing large executables
>with slow performance (due to paging).
>

Quality of implimentation issue? Where does the current C++ draft explicitly
say that one translation unit must compile into one segment? If the problem
is as bad as you say, then you're saying that languages such as Eiffel,
Modula-2, Ada, ... suffer a severe performance hit due to their modularity.
Is this indeed the case?

>Additionally, the committee have gone out of their way to allow things to
>be split over multiple places. eg a namespace can be split into multiple
>parts just be defining it in different spots.
>eg. (from Bjarne's great book D&E of C++)
>
> namespace Mine {
>   void f();
>        };
>
>        #include <stdio.h>
>
>        namespace Mine {
>          int g();
>        };
>
>Doing differently for the classes implementation is a gratuitous
>un-orthogonality.

But classes and namespaces are two different things, so where is the
non-orthogonality? You yourself mention this difference "a class
declaration can't be split up". There are advantages two both approaches
which is the issue I was trying to raise. Because of this and other questions,
it's not clear cut what the exact behaviour should be.

> (it's a pity a class declaration can't be split up, but I
>think most can see reason behind that).
>

Actually, this needn't be the case. It is possible to define things
so that only the public and protected sections of the class are visible.
It would require there to be only one implementation per class that
specifies the body of the private section. "sizeof" would have to
know the location of the compiled section and add it's size to the size
of the size of the public and private interface. <*blech*> It's possible
but I doubt anyone would consider the marginal gain to be worth the large
burden to the language.


>Regards,
> Rohan
>--
>----------------------------------------------------------------------------
>rjl@iassf.easams.com.au | All quotes can be attributed to my automated quote
>Rohan Lenard            | writing tool.  Yours for just $19.95; and if you
>+61-2-367-4555          | call now you'll get a free set of steak knives ...


--
/----------------------------------+------------------------------------------\
| Robert N. Deviasse               |"If we have to re-invent the wheel,       |
| EMAIL: g2devi@cdf.utoronto.ca    |  can we at least make it round this time"|
+----------------------------------+------------------------------------------/




Author: dag@control.lth.se (Dag Bruck)
Date: 04 Sep 1994 10:24:04 GMT
Raw View
>>>>> "J" == Jason Ozolins <jasonoz@cairo.anu.edu.au> writes:

[Most of proposal to avoid repeating e.g. template parameter list deleted.]

J> template <class X> implementation LongClassName {
J>    LongClassName(LongClassName &src) { .  .  .  }
J>    AnotherMemberFunction (...)  { .  .  }
J> }

J> I realise that it is well past the stage where the
J> standard can be influenced by idle suggestions, but if there is
J> enough interest in this I might write some kind of preprocessor to
J> take things written in this style and emit normal, unreadable C++
J> function definitions.

The strongest drawback of the proposal, as I see it, is that it
provides convenience but no new functionality.  I think someone said
that about references, too.

In any case, the suggested approach to

 1.  Implement the feature
 2.  See if people like it
 3.  Propose it for the next round of standardization

makes sense to me.
    -- Dag




Author: ghogenso@u.washington.edu (Gordon Hogenson)
Date: 5 Sep 1994 16:09:44 GMT
Raw View
rjl@f111.iassf.easams.com.au (Rohan LENARD) writes:

>Additionally, the committee have gone out of their way to allow things to
>be split over multiple places. eg a namespace can be split into multiple
>parts just be defining it in different spots.
>eg. (from Bjarne's great book D&E of C++)

> namespace Mine {
>   void f();
>        };

>        #include <stdio.h>

>        namespace Mine {
>          int g();
>        };

>Doing differently for the classes implementation is a gratuitous
>un-orthogonality (it's a pity a class declaration can't be split up, but I
>think most can see reason behind that).

Are you saying that it is possible to have:

foo.h:

   class Foo {
       Foo();
       ~Foo();
       foofunction();
    };

foo.cc:

   namespace Foo {
       Foo() { // ctor for Foo }
       ~Foo() { //dtor code }
    }

   //.... stuff

   namespace Foo {
       foofunction() { code for this function }
     };

Is this allowed?  Every class defines a namespace, does it not?
If this is the case, then allowing template namespaces solves the
original poster's problem without adding new keywords, and does so in a way
which is a natural extension to the existing standard.

namespace template <class T, class U> Foo
{

  Foo<T,U>()
    {
      // ctor for Foo<T,U>
    }

  // ...

}

Any objections?

Gordon Hogenson





Author: jasonoz@cairo.anu.edu.au (Jason Ozolins)
Date: 2 Sep 94 02:34:51 GMT
Raw View
Hi all,
  I am a member of a development group which has recently been involved
in doing code reviews, and after looking at zillions of template class
member function definitions which get to look like

template <class X> LongClassName<X>::LongClassName<X>
   (LongClassName<X> &src)
{
   .
   .
}

template <class X> LongClassName<X>::AMemberFunction (..)
{
   <5 lines of code which you didn't want inlined>
}

and seeing lots of function definitions which ended up inside the class
definition for (I suspect) the simple reason that it was a lot cleaner
to type that way, I came up with an idea to tidy up sets of member function
definitions.  A side effect of this is to reduce this unnatural tendency
for function definitions in hastily written template code to always end
up in the class declaration.

   How it goes: Introduce a new keyword (gasp!); let's call it
'implementation' for want of a better name.  When in your .cc file you want
to have a set of function definitions for some class with a nice long
descriptive name, you go

implementation LongDescriptiveName {

 LongDescriptiveName () {
 .
 <constructor code>
 .
 }

        AMemberFunction (....) {
        .
 .
 }

 <other function definitions, all of which are member functions
  of class LongDescriptiveName>
}

in a way exactly analogous to the usual 'class' keyword for a class
declaration.  The readability payoff is much greater for template class
member function definitions; the original gross example given above turns
into:

template <class X> implementation LongClassName {
   LongClassName (LongClassName &src)
   {
   .
   .
   .
   }

   AnotherMemberFunction (...)
   {
   .
   .
   }
}

which is IMHO much nicer.

Possible pitfalls of this idea:
-  There might be some nastiness in doing nested class member functions, but
   I can't see any problems at first glance....
-  It might encourage an indentation style which would break tools which
   depend on the function definition starting at the beginning of the line

   [feel free to mail me any more you think of]

I know that this sort of thing can be halfway done for non-template classes
with judicious typedefs; I believe that typedefs cannot really help you
when you need to do a whole set of template member function definitions.

I would really welcome any comments that people have on this suggestion;
I realise that it is well past the stage where the standard can be
influenced by idle suggestions, but if there is enough interest in this
I might write some kind of preprocessor to take things written in this
style and emit normal, unreadable C++ function definitions.

Apologies if this has (a) been suggested before and shot down, or (b)
something like it got into the draft standard when I wasn't looking.

Jason Ozolins
jasonoz@cairo.anu.edu.au