[comp.lang.c++] namespace

uh311ae@sunmanager.lrz-muenchen.de (Henrik Klagges) (02/04/91)

Hello !
Last year I proposed a change to the language that was quickly burned 
to ashes. However, I still like it, so here it is again:
1. the problem:
- 'that stupid programmer used 'object' as the name of his root thing in
   his tree class lib. Now I (the intelligent programmer) can't use that
   name ('object') anymore, if I still want to use the other lib.'
- 'I got that big chunk of PD source and tried to compile it. Now, the
   linker doesn't find _unknown_function_number_zillion+1. I know which
   file calls it, but it just includes a glob.h header fanning out into
   100 directions so that I could not trace the name down to the file where
   it actually should be defined.
   I grepped /usr/include, /usr/include/sys & bsd, *lib*, /*/local/* ---
   and finally made a low-level byte pattern search of the mounted discs to
   find the headers & libraries.'

2. A proposal:               
   I say, treat files as objects. I think that in OOP you either 'should be
   able to know *exactly*' OR 'shouldn't need to know'. You should never
   'need to know, but hell, how, where, if ...'. This means, if I use a name
   in a file, it must be resolvable without any ambiguity. Therefore it 
   is not enough to know that ' a name is external ' or ' thank god that it
   is somewhere up the include tree '. If it is known that a name is not de-
   fined within a file object, it must be possible to establish a single link
   to that name (which is within another file object), otherwise the rigid 
   OO environment breaks down. This could be accomplished in a Modula2/3-     
   fashion:

3. Example:
   Say, 'test.cxx' wants to use stdio printf capabilities. To make an 
   unambigous include, it needs to say: 'I want a printf thing from stdio'. It
   is not enough to say: 'I want stdio' or ' I want printf '. Printf is a 
   'structural subobject' of the 'structural object' stdio.h (while e.g. a
   'real number' would be a logical or functional subobject of a base class
   'number). OK. So test.cxx says: 

#include <stdio.h::printf>
printf("Hello World !\n");

   In this case it is clear what printf means - because it has been explicitly
   included as *the* printf. If I want to include more things from stdio, it 
   could be to much work to include them all in this way. Therefore, as in
   Modula, simply say:

#include <stdio.h>    
// BUT:
stdio::printf("Hello.\n");

   In this case it is known that stdio is included (so a name like stdio::*
   can be resolved). If I want to use printf, I have to precede it with the
   stdio::printf. In standard c/c++ the resolving would search the complete
   include/link tree - with all the nasty consequences.

4. Problems
   In case of interference with the overload mechanism, the explicit refe-  
   rence (stdio::printf) has to be used. 

Comments, flames, workarounds, etc. please.
Thank you.

Cheers ! Rick@vee.lrz-muenchen.de
(also uh33201@dm0lrz01.bitnet, uh33201@ymp.lrz-muenchen.de, uh311ae@sun7.l*
 Compuserve: 100014,353)

gregk@cbnewsm.att.com (gregory.p.kochanski) (02/05/91)

In article <uh311ae.665663860@sunmanager> uh311ae@sunmanager.lrz-muenchen.de (Henrik Klagges) writes:
>Hello !
>Last year I proposed a change to the language that was quickly burned 
>to ashes. However, I still like it, so here it is again:

>   I say, treat files as objects. I think that in OOP you either 'should be

>   Say, 'test.cxx' wants to use stdio printf capabilities. To make an 
>   unambigous include, it needs to say: 'I want a printf thing from stdio'.

>#include <stdio.h::printf>
>printf("Hello World !\n");
 --or--
>#include <stdio.h>    
>// BUT:
>stdio::printf("Hello.\n");
>
>   In this case it is known that stdio is included (so a name like stdio::*
>   can be resolved). If I want to use printf, I have to precede it with the
                                               ^^^^^^^^
>   stdio::printf. In standard c/c++ the resolving would search the complete
>   include/link tree - with all the nasty consequences.

Well, first, forcing the use of this feature would break all C and C++
code in the universe.  I don't think that that is desireable.

Compilers would presumeably be forced to add more decoration to a function
name '5stdio5printfFe' or something like that, but that's O.K.

It seems a little sloppy to use the function name -- you might run into
various operating-system-dependent obscurities (like MS-DOS doesn't
know about small letters).  Declaring the name of a module with some
statement might be better, perhaps
extern "C++::modulename" {  module here }
or something that isn't yet used.  This would also keep the seperation
between the preprocessor and the compiler intact.

I like the idea, but don't think that I'm an authority.

horstman@mathcs.sjsu.edu (Cay Horstmann) (02/06/91)

In article <4e2Gwz9f@cs.psu.edu> schwartz@karl.cs.psu.edu (Scott Schwartz) writes:
>
>gregk@cbnewsm.att.com (gregory.p.kochanski) writes:
>   Well, first, forcing the use of this feature would break all C and C++
>   code in the universe.  I don't think that that is desireable.
>
>Without commenting on the specific proposal that inspired this reply,
>I observe that this very argument has been used to nuke all sorts
>suggestions in the past, which is a shame.  

I absolutely concur.

Look at ANSI C function prototypes. They were upwardly compatible with 
K&R C. Starting with C++ Version 2 and type-safe linkage, the compatibility
is basically gone. You can still link K&R C and C++, but you can no longer
mix source code in the same file. You CAN, however, often use the same
compiler, with different flags, to compile K&R C and C++ code, if you have
to.

Look at "assignment to this". Here is a classical example of a poorly
thought out feature in a new language. There should be some way of getting
rid of those features when necessary. 

There are lots of dumb syntactical quirks in C++. For example, it would
be very rational to use "private" and "public" on the module level instead
of "static" and "". 

I for one wish that the ANSI C++ committee had the courage to address 
these issues and do these cleanups [I have lots more to suggest] once
and for all, no matter how much C code they break. Of course their choice
of the ARM as the "base document" doesn't look promising. 

I have followed with great interest the discussion on smart pointers and
on namespace problems and find that some solutions to these problems should
be incorporated into a future version of C++. But the mantra "it will 
break gobs of old code" can easily frustrate all discussion. 

Cay

gregk@cbnewsm.att.com (gregory.p.kochanski) (02/07/91)

In article <1991Feb6.155227.553@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>I for one wish that the ANSI C++ committee had the courage to address 
>these issues and do these cleanups [I have lots more to suggest] once
>and for all, no matter how much C code they break.
>
>But the mantra "it will 
>break gobs of old code" can easily frustrate all discussion. 

1) I don't know how big the existing base of C++ code is, but I'm not
volunteering to spend the rest of my life updating it because of
unnecessary incompatibilities.  Perhaps Mr. Horstmann is.

2)  My comment about 'breaking existing code' was in reference to a part
of the proposal that did not seem central to me.  Specifically, the proposer
seemed to want to make use of his mechanism mandatory, and I'd just
as soon make it optional.  Will the flamers please state why it must be
mandatory?

horstman@mathcs.sjsu.edu (Cay Horstmann) (02/07/91)

In article <1991Feb6.222339.17017@cbnewsm.att.com> gregk@cbnewsm.att.com (gregory.p.kochanski) writes:
>In article <1991Feb6.155227.553@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>>I for one wish that the ANSI C++ committee had the courage to address 
>>these issues and do these cleanups [I have lots more to suggest] once
>>and for all, no matter how much C code they break.
>>
>>But the mantra "it will 
>>break gobs of old code" can easily frustrate all discussion. 
>
>1) I don't know how big the existing base of C++ code is, but I'm not
>volunteering to spend the rest of my life updating it because of
>unnecessary incompatibilities.  Perhaps Mr. Horstmann is.
>
I am not sure how wise it is to turn to C++ TODAY if one is unwilling to
live with a changing language. 

I had to do LOTS of reworking with "extern C" when type-safe linkage came out.
I still have some "assignments to this" in some old code and expect to have to
redo them when my next compiler won't support them anymore. 

That is just fine with me. I know C++ is currently an evolving language
and I know what I am getting into by using it now. 

Anyway, the compiler designers can easily support "C++ Ver.1", "Ver.2.0",
"Ver.2.1" flags for a while, just as they now have "ANSI C" and "K&R C"
flags.

Cay

mike@taumet.com (Michael S. Ball) (02/08/91)

In article <1991Feb6.155227.553@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>I for one wish that the ANSI C++ committee had the courage to address 
>these issues and do these cleanups [I have lots more to suggest] once
>and for all, no matter how much C code they break. Of course their choice
>of the ARM as the "base document" doesn't look promising. 

The ANSI committee doesn't feel that it has a mandate to develop a new
language, but rather to standardize an existing one.  Almost all of the
problem areas in C++ are those where the desire to maintain C compatibility
clashed with the desire to support some new feature.  Many of us would
like to get rid of them.  Those of us who want to see C++ used are
pretty well resigned to their continued presence.

It's not a matter of courage at all.
-- 
Michael S. Ball			mike@taumet.com
TauMetric Corporation		(619)697-7607

jbuck@galileo.berkeley.edu (Joe Buck) (02/28/91)

In article <1991Feb10.024111.8967@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
|> In article <592@taumet.com> mike@taumet.UUCP (Michael S. Ball) writes:
|> >The ANSI committee doesn't feel that it has a mandate to develop a new
|> >language, but rather to standardize an existing one.  
|> 
|> And I think it is unfortunate that the ANSI committee feels that way.
|> Clearly the ANSI C committee did not, and as a result C became a much
|> better language.

Even the ANSI C committee didn't feel they had a mandate to create a
new language.  The new features added (such as function prototypes)
weren't invented out of thin air.  Instead, they were taken from an
existing language: C++.

--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

scu@otter.hpl.hp.com (Shankar Unni) (03/01/91)

In comp.lang.c++, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
> >In article <1991Feb6.155227.553@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
> >>I for one wish that the ANSI C++ committee had the courage to address 
> >>these issues and do these cleanups [I have lots more to suggest] once
> >>and for all, no matter how much C code they break.
> >>
> >> the mantra "it will break gobs of old code" can ... frustrate discussion. 
>
> I am not sure how wise it is to turn to C++ TODAY if one is unwilling to
> live with a changing language. 

> I had to do LOTS of reworking with "extern C" when type-safe linkage came out.
> I still have some "assignments to this" in some old code and expect to have to
> redo them when my next compiler won't support them anymore. 

> That is just fine with me. I know C++ is currently an evolving language
> and I know what I am getting into by using it now. 

I can understand the frustration of those who would like to see a lot of
language ills corrected, when we (apparently) have a chance to do so in the
ANSI committee, rather than have to wait and invent yet another language
later.

Still, there should be a sense of balance when introducing brand new
features into the language. The ANSI C committee tried very hard to only
introduce things that had already been experimented with (with one
gruesome exception: trigraphs, which should stand as a banner example of
the sort of things that get created by committee).

It's very important to gain "prior expertise" before deciding on a standard
form of it:

  (a) Is it possible, and preferably, easy to implement?
  (b) Are its semantics well understood (esp. corner cases and interaction
      with the rest of the features of the language)?
  (c) Do we have sufficient programming expertise with it?
  (d) Does it gratuitously break existing code?
  (e) Is it *really* necessary?

Each of these criteria is important in its own way. The first two are
obvious, and it is clear that no answer to them can be provided without
first implementing the feature in some experimental compiler (usually
gcc/g++, or its likes).

Once all the potential problems are ironed out, we come to criterion (c).
Is this the correct answer to the problem we are trying to solve? Is there
 a "better" way of achieving it? This may mean mean several passes over the
feature until it is "neat" and "compact", and fits in with the rest of the
language. (This is where a lot of the subjective judgement comes in. We try
not to introduce too many new keywords, or unnecessary syntactic sugar, and
try to meld it into the existing language.)

Criterion (d) is the sticking point mentioned previously. Admittedly, C++
is an evolving language. However, for people to gain *real* expertise in
the language, it must be quasi-stable (i.e. not frozen, but at least of a
jelly-like consistency :-), or "commercial" (read: "real") customers won't
be willing to touch it.

Finally, criterion (e) has also been invoked several times. The idea here
is to prevent C++ from becoming the PL/I (or Ada) of the 90s.  The "kitchen
sink" principle is attractive to many academics, but it becomes impractical
in the real world, where people have to:

   - write compilers.
   - be trained in the language - a language that is too big has too steep
     a learning curve.
   - write code using the language - if the features are ill-thought-out,
     there is a real problem in choosing the right feature-set to implement
     programs in.
   - read and understand other peoples' code - see point 2 above.

Thus, a feature should be added or modified only if it is seen to cover an
important piece of missing functionality, and there is no easy way to
achieve the same using some combination of existing functionality.

There are several conflicting forces acting on the committee, and they have
to be very picky in selecting and modifying features, if they are not to
create a monster. ("Two-headed dinosaur created in lab!").
-----
Shankar Unni                                   E-Mail: 
Hewlett-Packard Laboratories, Bristol        Internet: shankar@cup.hp.com
Phone : +44-272-799910 x24284                    UUCP: ...!hplabs!hpda!shankar

P.S. The current exception-handling debates in the committee should be an
interesting test of the criteria above. I believe several committee members
are rushing ahead to implement this feature in order to gain expertise with
it.

scu@otter.hpl.hp.com (Shankar Unni) (03/01/91)

In comp.lang.c++, uh311ae@sunmanager.lrz-muenchen.de (Henrik Klagges) writes:

> 2. A proposal:               
>    I say, treat files as objects. [...] This means, if I use a name
>    in a file, it must be resolvable without any ambiguity. Therefore it 
>    is not enough to know that ' a name is external ' or ' thank god that it
>    is somewhere up the include tree '. If it is known that a name is not de-
>    fined within a file object, it must be possible to establish a single link
>    to that name (which is within another file object), otherwise the rigid 
>    OO environment breaks down. This could be accomplished in a Modula2/3-     
>    fashion:

> 3. Example:

> #include <stdio.h::printf>
> printf("Hello World !\n");

>    In this case it is clear what printf means - because it has been explicitly
>    included as *the* printf. If I want to include more things from stdio, it 
>    could be to much work to include them all in this way. Therefore, as in
>    Modula, simply say:

> #include <stdio.h>    
> // BUT:
> stdio::printf("Hello.\n");

After the last homily, I'll address this feature. This looks like an
interesting extension to the language, well in the vein of the existing
functionality.

Some of the objections ("breaks existing code") can be easily countered by
providing that if there is only one definition of a symbol, then module
qualification is not required:

  #include <stdio.h>
  printf ("hello\n");	// if this is the only declared or imported printf.

We thus cover (d) quite adequately. Now for (a), (b) and (c).

Someone (I'm *not* volunteering :-) needs to implement this feature,
preferably in gcc/g++, and try it out. How about using it on, say, the NIH
library (which does declare an "Object"), and something else which does the
same? 

One would have to tweak NIH a little: "class Foobar : NIH::Object { .. };"

But then, one is also forced to ask the question (e). Is this any better
than if Keith G. had originally written:

  class NIHObject { };
  class Foobar: NIHObject { };

I.e. instead of a syntactic module qualification, just prepend some unique
prefix?

I can't think of anything addressed by this proposal that could not have
been just as easily solved by the above technique. Does the feature provide
for the user to randomly throw in libraries, and have "DWIM" qualifications
take place? I think not: he would have to edit all the files and add the
qualifications regardless. Even if some implicit qualification is allowed,
he would still have to qualify everything for safety. How is this different
from just using more unambiguous and unique names?

I would, thus, at first glance, vote NO on this feature. But if someone can
implement this and convince me as to how it solves this (admittedly
important) problem in a novel way that is much easier and cleaner than
existing technology, I might go for it.
-----
Shankar Unni                                   E-Mail: 
Hewlett-Packard Laboratories, Bristol        Internet: shankar@cup.hp.com
Phone : +44-272-799910 x24284                    UUCP: ...!hplabs!hpda!shankar

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/02/91)

In article <11496@pasteur.Berkeley.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes:
>In article <1991Feb10.024111.8967@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
>|> In article <592@taumet.com> mike@taumet.UUCP (Michael S. Ball) writes:
>|> >The ANSI committee doesn't feel that it has a mandate to develop a new
>|> >language, but rather to standardize an existing one.  
>|> 
>|> And I think it is unfortunate that the ANSI committee feels that way.
>|> Clearly the ANSI C committee did not, and as a result C became a much
>|> better language.
>
>Even the ANSI C committee didn't feel they had a mandate to create a
>new language.  The new features added (such as function prototypes)
>weren't invented out of thin air.  Instead, they were taken from an
>existing language: C++.
>
>--
This is a fascinating discussion, and it is easy to project one's
own hopes and wishes into the ANSI process.

Is ANSI C++ to be a codification of the language, as it exists today, 
warts and all? Then clearly exception handling should NOT be part of it.

Should ANSI C++ radically reform the syntax and semantics? I don't think
so, but neither does anyone else.

Should ANSI C++ give DIRECTION to the language, by eliminating some warts
(instead of codifying them) and providing genuine improvements (like ANSI
C did with function prototypes?) I think it should, but obviously many
people disagree: "It would break existing code..." 

By the way, Joe's argument really doesn't hold a lot of water: How would
we all feel if ANSI took over great ideas from Eiffel (an existing language...)?

Anyway, I think the ANSI committee is by its very nature inclined to be
very conservative--there are many vendors and users in it with a great
interest in keeping the status quo. Some netters share that attitude, but
others do not and keep on proposing new ideas (many of them useful, I think.)

Cay

jimad@microsoft.UUCP (Jim ADCOCK) (03/02/91)

In article <615@taumet.com> mike@taumet.UUCP (Michael S. Ball) writes:
|In article <1991Feb10.024111.8967@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
|>In article <592@taumet.com> mike@taumet.UUCP (Michael S. Ball) writes:
|>>The ANSI committee doesn't feel that it has a mandate to develop a new
|>>language, but rather to standardize an existing one.  
|>
|>And I think it is unfortunate that the ANSI committee feels that way.
|>Clearly the ANSI C committee did not, and as a result C became a much
|>better language.
|
|But that is the approach taken by the ANSI C committee.  Lack of implementation
|experience was the basic argument against a variety of "nice" extensions.
|
|I do not believe that the two committees differ much in this regard.
|The C++ committee has already stepped beyond existing implementations by
|adding templates and exceptions.  Nonetheless, from all I have seen the
|committee itself (unlike proposals from the field) is taking a very
|conservative approach to language changes.  Personally, I think it is
|fortunate, since our experience with language design by standards committees
|hasn't been good.

I tend to agree, but then the result is that it is up to the compiler
vendors to implement the "fixes" that C++ needs in incompatible ways,
and then at some point in time in the future, a committee has to 
reconvene and try to figure out how to standardize on "C+=2"

I think we have to admit that there's going to areas that the committee
can't get agreement on.  But being totally conservative leaves too
much to be resolve and/or fixed "the next time."  The right approach falls
somewhere between being totally conservative and totally liberal.  Right
now, the approach seems to me to be falling in the "totally conservative"
camp:  "Let's just rubber stamp ARM and get out of here."

rfg@NCD.COM (Ron Guilmette) (03/03/91)

In article <2620020@otter.hpl.hp.com> scu@otter.hpl.hp.com (Shankar Unni) writes:
+In comp.lang.c++, uh311ae@sunmanager.lrz-muenchen.de (Henrik Klagges) writes:
+
+> 2. A proposal:               
+>    I say, treat files as objects. [...] This means, if I use a name
+>    in a file, it must be resolvable without any ambiguity...
...
+> 3. Example:
+
+> #include <stdio.h::printf>
+> printf("Hello World !\n");

This is not a great example, because Henrik should be using C++ streams
instead of the crusty old C I/O routines. Still, we get Henrik's point.

+>    In this case it is clear what printf means - because it has been explicitly
+>    included as *the* printf. If I want to include more things from stdio, it 
+>    could be to much work to include them all in this way. Therefore, as in
+>    Modula, simply say:
+
+> #include <stdio.h>    
+> // BUT:
+> stdio::printf("Hello.\n");
...
+But then, one is also forced to ask the question (e). Is this any better
+than if Keith G. had originally written:
+
+  class NIHObject { };
+  class Foobar: NIHObject { };
+
+I.e. instead of a syntactic module qualification, just prepend some unique
+prefix?
+
+I can't think of anything addressed by this proposal that could not have
+been just as easily solved by the above technique. Does the feature provide
+for the user to randomly throw in libraries, and have "DWIM" qualifications
+take place? I think not: he would have to edit all the files and add the
+qualifications regardless. Even if some implicit qualification is allowed,
+he would still have to qualify everything for safety. How is this different
+from just using more unambiguous and unique names?
+
+I would, thus, at first glance, vote NO on this feature. But if someone can
+implement this and convince me as to how it solves this (admittedly
+important) problem in a novel way that is much easier and cleaner than
+existing technology, I might go for it.

Namespace pollution is indeed an important and, I believe, an unsolved
problem in C++.

The idea proposed here is to use include files as individual namespace
"modules".  That's not a bad idea, however C++ already has something
which can serve pretty well as a namespace "module".  It's called a
class.  Consider a header file like:

	incl.h:
	--------------------------------------------------------------------
	extern int somedata;

	typedef double* double_p_type;

	extern void myfunc (double, char);
	--------------------------------------------------------------------

Ask yourself if there are any reasons why this could not be rephrased as:

	incl.h:
	--------------------------------------------------------------------
	class incl {
	public:
		static int somedata;

		typedef double* double_p_type;

		static void myfunc (double, char);
	};
	--------------------------------------------------------------------

Now if we include this into some other file (or files) we should be able
to refer to `incl::somedata', `incl::double_p_type', and `incl::myfunc'.

Presto!  No more namespace pollution problems.  Right?  Well... not quite.

The problem with this scheme is that we are now *forced* to *always*
provide explicit qualification for anything we get from `incl.h'.  If
you are lazy (like me) this will seem to be a large and unnecessary hassle.

For example, I might have to write:

	--------------------------------------------------------------------
	#include <incl.h>

	double d;

	void foobar ()
	{
		incl::double_p_type dp = &d;

		incl::myfunc (dp, (char) incl::somedata);
	}
	--------------------------------------------------------------------

Is there a solution?  Sure.  We could introduce a `with' statement (as in
Pascal) which could specify that within a given region, a particular class
type should be used for implicit qualification (when necessary), e.g.:

	--------------------------------------------------------------------
	#include <incl.h>

	double d;

	void foobar ()
	{
	    with (incl)
	    {
		double_p_type dp = &d;

		myfunc (dp, (char) somedata);
	    }
	}
	--------------------------------------------------------------------

In the example here, the thing mentioned in the "qualifier" clause of
the `with' statement is a type (rather than an object designator, as in
Pascal).  Actually, I can see the usefulness of *both* possible forms
of `with' statements in C++ (i.e. `with' statements specifying types
and `with' statements specifying particular objects).  Both forms
could lead to less verbose C++ programs.  (I'm not really sure if that's
an argument in favor of `with' statements or against them. :-)

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// New motto:  If it ain't broke, try using a bigger hammer.

wmm@world.std.com (William M Miller) (03/03/91)

horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
> Is ANSI C++ to be a codification of the language, as it exists today,
> warts and all? Then clearly exception handling should NOT be part of it.
>
> Should ANSI C++ give DIRECTION to the language, by eliminating some warts
> (instead of codifying them) and providing genuine improvements (like ANSI
> C did with function prototypes?) I think it should, but obviously many
> people disagree: "It would break existing code..."
>
> Anyway, I think the ANSI committee is by its very nature inclined to be
> very conservative--there are many vendors and users in it with a great
> interest in keeping the status quo. Some netters share that attitude, but
> others do not and keep on proposing new ideas (many of them useful, I think.)

[Please note that the following comments are my personal perspective, not a
statement of policy on behalf of X3J16, X3, or ANSI.]

I believe it is accurate to characterize X3J16 as having a basically
conservative approach to the standardization process.  However, I do not
think that Cay is correct in attributing this conservatism to vendors and
users with vested interests in preserving the status quo.  Instead, I see
several other factors at work.

A large part of our attitude on the committee comes from examining the
experience of X3J11, the C standard committee.  For every change they made,
the C committee had to endure *megabytes* of net flamage from irate critics
claiming they were mad innovators betraying their mandate.  Even to this day
there are still postings complaining about as obvious and apparently
noncontroversial a feature as prototypes.  It's true that there are always
those who propose specific changes or extensions, but the user community as
a whole is fundamentally conservative, desiring to preserve existing
investments in code and training, and achieving anything like consensus in
favor of any given change is a very difficult thing to do.  Look at the
outrage in the FORTRAN and COBOL communities over the innovations being
discussed in their respective standards committees.

Because we realize that there will inevitably be changes we cannot avoid, we
are very cautious about making "optional" changes that would improve
esthetics ("eliminate warts") but that are in no sense mandatory.  Our
credibility and good will in that conservative user community is a limited
resource; we must husband it carefully for use in the battles that really
matter and not squander it over dozens of minor issues.

Someone earlier (sorry, I don't have the article online any more so I can't
attribute it) mentioned the negative experience of language design by
committee.  That is also an issue to which we are sensitive.  The poster
mentioned trigraphs as an example; the more often cited feature is
"noalias," which did not make it into the final C standard but which was
accepted by the committee at one point.  We're even experiencing some of the
trials of design on the fly right now; even though the proposal for
templates has been publicly available for some time, going back to the 1988
USENIX C++ Conference, and was accepted at the July, 1990 meeting, we spent
a good deal of time at the November meeting reconsidering the syntax because
of ambiguities in the current specification, and we'll spend more time on it
in the meeting next week.

The point I'm making is that it's awfully hard to create a language feature
out of whole cloth; user experience is always needed to verify the "safety
and effectiveness" of even small and apparently well-understood changes.
The way to avoid a multiplicity of dialects for new features is to get the
compiler writers to talk to each other (and there's a great deal of that in
the C++ community, happily), not to put something into the standard and hope
that it flies.  Standards have legal implications and are awfully hard to
change; they are not the venue of choice for language innovation.

A final consideration is time.  Given the rate of growth of C++ in both
number of users and number of implementations, we need a firm standard in
place last year, yet even with our intent to reflect the existing langauge
rather than design a new one, we probably won't have one until 1994.  Bjarne
says he has a pile of "useful" suggestions several inches thick; we could
easily be into the next century without a standard if the committee took a
more proactive role in modifying the existing language.  Again, look at the
delays being experienced by more activist standards bodies.

As a final note to this already overlong posting, let me say that exception
handling and templates are special cases for several reasons.  First, there
is almost universal agreement that they are needed in order to achieve the
benefits of reusability and extensibility C++ promises; such unanimity in
favor of other proposed features is going to be hard to come by.  Second,
both are based on proposals that have been very widely disseminated outside
the committee so that the user community as a whole has had the chance to
study and comment.  Third, the original proposal for the standardization
effort accepted by X3 included these two features specifically as within the
purview of the committee's work.  Finally, and very importantly, both
features are pure extensions; the only code that might break as a result of
incorporating them into the standard is that compiled using experimental
implementations, and presumably the owners of that code used those features
with their eyes open to the fact that changes would almost certainly be
required once a standard was adopted.  Many of the other features being
proposed are not nearly so benign.

This is not to say that *no* changes to E&S will be adopted; there have
already been a few, and there will no doubt be more in the future.  However,
proposed changes that are simply "useful" will probably face tough sledding;
only those that address a compelling need that demonstrably outweighs the
above considerations are likely to fly, IMHO.

-- William M. Miller, Glockenspiel, Ltd.
   wmm@world.std.com

schemers@vela.acs.oakland.edu (Roland Schemers III) (03/04/91)

In article <4196@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
>
>Namespace pollution is indeed an important and, I believe, an unsolved
>problem in C++.
>
>The idea proposed here is to use include files as individual namespace
>"modules".  That's not a bad idea, however C++ already has something
>which can serve pretty well as a namespace "module".  It's called a
>class.  Consider a header file like:

I just had namespace pollution spoil my weekend. We just got in Motif
from DEC, and it has C++ compatible headers, so I was all set to 
start hacking away... Till I noticed they had a 'typedef char *String;'
which was used extensivly through all the headers. Now I can't use
my handy dandy String class that is part of my library. So I basically
had to redesign my library. 

I had to choices:

1. Make a class that contained all my classes, and access my String class
   like RJS::String

2. Prefix all my objects with RJS_

I picked number 2. Now all my objects begin with RJS_ (Roland J Schemers :-)).
This does lead to very verbose objects:

RJS_PrinterQueueIterator

For example, but it does protect me for the most part. Until someone starts
using their own RJS_ prefix!!!

To get over verbose names I think I am going to make an include file called
<RJS/Type.h> (all my includes are in their own directory), which contains:

#ifndef RJS_TYPE_H
#define RJS_TYPE_H

class RJS_String;
typedef RJS_String String;

#endif

... more classes...

#endif

This file could be modified to avoid namespace problems.
Of course one this happens all the code that used the typedef
version must be changed! So for now I am just using the verbose
RJS_ names of all my objects.

Either way this is something that needs to be dealt with.

Roland
-- 
Roland J. Schemers III                              Systems/Network Manager
schemers@vela.acs.oakland.edu (Ultrix)              Oakland University 
schemers@argo.acs.oakland.edu (VMS)                 Rochester, MI 48309-4401
You can tune a piano, but you can't tuna VMS!       (313)-370-4323

wmm@world.std.com (William M Miller) (03/04/91)

rfg@NCD.COM (Ron Guilmette) writes:
> Consider a header file like:
>
>         incl.h:
>         --------------------------------------------------------------------
>         extern int somedata;
>
>         typedef double* double_p_type;
>
>         extern void myfunc (double, char);
>         --------------------------------------------------------------------
>
> Ask yourself if there are any reasons why this could not be rephrased as:
>
>         incl.h:
>         --------------------------------------------------------------------
>         class incl {
>         public:
>                 static int somedata;
>
>                 typedef double* double_p_type;
>
>                 static void myfunc (double, char);
>         };
>         --------------------------------------------------------------------
>
> Now if we include this into some other file (or files) we should be able
> to refer to `incl::somedata', `incl::double_p_type', and `incl::myfunc'.
> The problem with this scheme is that we are now *forced* to *always*
> provide explicit qualification for anything we get from `incl.h'.
> Is there a solution?  Sure.  We could introduce a `with' statement (as in
> Pascal) which could specify that within a given region, a particular class
> type should be used for implicit qualification (when necessary)

I don't think a "with" statement is really necessary.  Consider the
following version of incl.h:

        incl.h
        -----------------------------------------------------------------
        class incl {
        public:
                static int somedata;

                typedef double* double_p_type;

                static void myfunc(double, char);
                };

        #ifndef QUALIFIED

        int& somedata = incl::somedata;

        typedef incl::double_p_type double_p_type;

        void (*myfunc)(double, char) = incl::myfunc;

        #endif
        -----------------------------------------------------------------

With this kind of header, if you don't have name conflicts, you simply
include the header and use the unqualified names.  If you do have
conflicts, simply #define QUALIFIED before including the header and only the
"incl::" qualified names will be seen (of course, there's nothing to stop a
compilation unit from using the QUALIFIED version and extracting via
typedef, reference, or function pointer any frequently-used non-conflicting
individual names).  This corresponds roughly to qualified and unqualified
export in Modula-2.

Another thought that corresponds more closely to "with" would be to put the
stuff in the "#ifdef QUALIFIED" section into another include file, say,
withincl.h; incl.h would have only the "incl::" qualified names.  Ron's
"with" example becomes something like:

	--------------------------------------------------------------------
	#include <incl.h>

	double d;

	void foobar ()
	{
	    {
        #include <withincl.h>
		double_p_type dp = &d;

		myfunc (dp, (char) somedata);
	    }
	}
	--------------------------------------------------------------------

-- William M. Miller, Glockenspiel, Ltd.
   wmm@world.std.com

horstman@mathcs.sjsu.edu (Cay Horstmann) (03/04/91)

In article <5318@vela.acs.oakland.edu> schemers@vela.acs.oakland.edu (Roland Schemers III) writes:
>
>I had to choices:
>
>1. Make a class that contained all my classes, and access my String class
>   like RJS::String
>
>2. Prefix all my objects with RJS_
>
>I picked number 2. Now all my objects begin with RJS_ (Roland J Schemers :-)).

You are in good shape now ... until you start getting code from Richard J 
Stallman.

Cay

jimad@microsoft.UUCP (Jim ADCOCK) (03/05/91)

In article <4196@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
|Is there a solution?  Sure.  We could introduce a `with' statement (as in
|Pascal) which could specify that within a given region, a particular class
|type should be used for implicit qualification (when necessary), e.g.:
|
|	--------------------------------------------------------------------
|#include <incl.h>
|
|double d;
|
|void foobar ()
|{
|    with (incl)
|    {
|	double_p_type dp = &d;
|
|	myfunc (dp, (char) somedata);
|    }
|}
|--------------------------------------------------------------------

How about something like:

#include <incl.h>

double d;

void foobar()
{
    struct incl_ : public incl 
    { 
        static void with()
        {
            double_p_type dp = &d;
    
            myfunc (dp, (char) somedata);
        }
    }; 
    incl_::with();
}

suitably macro-hacked, this becomes:

void foobar()
{
    with(incl)
    {
        double_p_type dp = &d;

        myfunc (dp, (char) somedata);
    } 
    end_with(incl)

} 

1/2 :-}

rsalz@bbn.com (Rich Salz) (03/08/91)

In <5318@vela.acs.oakland.edu> schemers@vela.acs.oakland.edu (Roland Schemers III) writes:
>I just had namespace pollution spoil my weekend. We just got in Motif
>from DEC, and it has C++ compatible headers, so I was all set to 
>start hacking away... Till I noticed they had a 'typedef char *String;'

Here's what I do when something like this happens:
	#define String MOTIF_STRING
	#include <motif/mongo.h>
	#include <motif/sunsux.h>
	...
	#undef MOTIF_STRING
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.

vaitl@ucselx.sdsu.edu (Eric Vaitl) (03/09/91)

In article <3353@litchi.bbn.com> rsalz@bbn.com (Rich Salz) writes:
>In <5318@vela.acs.oakland.edu> schemers@vela.acs.oakland.edu (Roland Schemers III) writes:
>>I just had namespace pollution spoil my weekend. We just got in Motif
>>from DEC, and it has C++ compatible headers, so I was all set to 
>>start hacking away... Till I noticed they had a 'typedef char *String;'
>
>Here's what I do when something like this happens:
>	#define String MOTIF_STRING
>	#include <motif/mongo.h>
>	#include <motif/sunsux.h>
>	...
>	#undef MOTIF_STRING
>-- 
   Does that really work? It looks like you are trying to use the 
preprocessor to undefine something that doesn't even exist until
the typedef statement is compiled. If you have a compiler without
a seperate preprocessor, I could imagine the undef statment removing
MOTIF_STRING from the symbol table, but that would just be a bug
in your compiler. 

rfg@NCD.COM (Ron Guilmette) (03/10/91)

In article <1991Mar4.055223.19716@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
+In article <5318@vela.acs.oakland.edu> schemers@vela.acs.oakland.edu (Roland Schemers III) writes:
+>
+>I had to choices:
+>
+>1. Make a class that contained all my classes, and access my String class
+>   like RJS::String
+>
+>2. Prefix all my objects with RJS_
+>
+>I picked number 2. Now all my objects begin with RJS_ (Roland J Schemers :-)).
+
+You are in good shape now ... until you start getting code from Richard J 
+Stallman.

Fortunately, Richard's middle initial is `M' not `J', so Roland Schemers
is safe (for the moment :-).
-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// New motto:  If it ain't broke, try using a bigger hammer.