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