Topic: Macros vs namespace


Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/09/09
Raw View
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
>David Harmon wrote:
>> "using namespace std" apparently discards any advantage that might be
>> gained by having namespace std in the first place.  Do you feel, then,
>> that namespace std was a mistake?
>
>That's not true.
>
>"using namespace std" allows you to use names without prefixing them
>with "std::", however it doesn't *force* you to do so. In case of
>ambiguities, you still can revert to the "std::" notation.
>...
>* With namespaces, but without using:
>
>You have to prefix *every* std library symbol with "std::".

Not so.  You can say "using std::cout;" and similar for other
frequently-used names.

>This gives more work for the moment, but may save some work in case a
>later library change adds a new name that clashes with a std library
>name.  However, since the compiler catches such problems on compile,
>I'd view the change when needed as the simpler alternative, especially
>since such a name clash is unlikely anyway, and since even if it occurs,
>the work is still less since the std:: prefix must be put in front
>of only the conflicting names, instead of all names, and the places
>are well told from the compiler (it could even be automated using
>the compiler output).

This assumes that you actually get a compiler error.  What if
the non-standard name is a function, and actually a "better match"?
Then your program just fails.  Anyway, if you do get a compiler
error, how does the poor maintenance programmer know what to qualify
the name with?  (Surely std:: isn't the *only* namespace used in the
program.)

This places a responsibility on maintenance programmers that could
have been dealt with once and for all.  In sloppy shops I expect it
will be the norm, but I have higher hopes for more-professional
organizations.

--
Nathan Myers
ncm@nospam.cantrip.org  http://www.cantrip.org/



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






Author: Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/09/08
Raw View
In article <35fa9794.43922179@nntp.ix.netcom.com>,
David Harmon <source@netcom.com> wrote:
>On 5 Sep 1998 23:46:31 GMT, "P.J. Plauger" <pjp@dinkumware.com> wrote:
>
>>> Everyone seems to say that a global "using namespace std" is a
>>> bad thing,
>>
>>Not everyone. I don't. But then...
>
>"using namespace std" apparently discards any advantage that might be
>gained by having namespace std in the first place.

Not true for the following reasons:

* It can only discard the advantage for the program using namespace std.

Some program can have std::xxx and others 'using namespace std' and
both have suitable protection against namespace collisions.

This might seem like a trivial observation, but one of the goals
of the design of C++ was that you should only have to deal with the
features of the language that you actually use.

For projects that don't need namespaces global 'using namespace std'
achieves this goal. Disallowing global 'using namespace std' would
thus have been contrary to the spirit of C++ by forcing every program
to use namespaces even if not necessary.

* It only diminishes (not discards) the advantage for the individual
program. Namespace collisions can be handled by explicit
using-declarations even if 'using namespace std'.


--
// Home page  http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]




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






Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1998/09/08
Raw View
source@netcom.com (David Harmon) writes:

>On 5 Sep 1998 23:46:31 GMT, "P.J. Plauger" <pjp@dinkumware.com> wrote:
>
>>> Everyone seems to say that a global "using namespace std" is a
>>> bad thing,
>>
>>Not everyone. I don't. But then...
>
>"using namespace std" apparently discards any advantage that might be
>gained by having namespace std in the first place.  Do you feel, then,
>that namespace std was a mistake?

`using namespace std' is a fine solution to the problem of
porting between pre-standard and standard implementations.
That doesn't mean that putting namespace `std' in the standard
was a mistake.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3        |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: AllanW@my-dejanews.com
Date: 1998/09/09
Raw View
In article <35fa9794.43922179@nntp.ix.netcom.com>,
  source@netcom.com (David Harmon) wrote:
> On 5 Sep 1998 23:46:31 GMT, "P.J. Plauger" <pjp@dinkumware.com> wrote:
>
> >> Everyone seems to say that a global "using namespace std" is a
> >> bad thing,
> >
> >Not everyone. I don't. But then...
>
> "using namespace std" apparently discards any advantage that might be
> gained by having namespace std in the first place.  Do you feel, then,
> that namespace std was a mistake?

Using that same logic, you could explain that code using
floating-point numbers discards any speed advantage that might be
possible using integer types. Do you feel that using floating-point
numbers is a mistake?

Some programs benefit from "using namespace std" -- specifically,
old working programs which do not need namespace features, and
short demonstration programs that illustrate a technique (and will
not be used in production code).  Some programs benefit from full
and proper use of namespaces -- specifically, any project where
more than one programmer will work on the code, or any project
where third-party libraries are being written or used.

Use the proper tools for the job. As somebody famous (who?) said,
"When your only tool is a hammer, the world starts to look like
a nail..."

--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp   Create Your Own Free Member Forum


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






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/09/09
Raw View
David Harmon wrote:
>
> On 5 Sep 1998 23:46:31 GMT, "P.J. Plauger" <pjp@dinkumware.com> wrote:
>
> >> Everyone seems to say that a global "using namespace std" is a
> >> bad thing,
> >
> >Not everyone. I don't. But then...
>
> "using namespace std" apparently discards any advantage that might be
> gained by having namespace std in the first place.  Do you feel, then,
> that namespace std was a mistake?

That's not true.

"using namespace std" allows you to use names without prefixing them
with "std::", however it doesn't *force* you to do so. In case of
ambiguities, you still can revert to the "std::" notation.

Consider f.ex. the following:


* Without namespaces:

A vendor supplied the following linalg.h, which was written before STL:

template<class Num> class vector { ... };
template<class Num> class matrix { ... };

Since the name vector is already taking in the std library, you are in
trouble if you want to use both (and possibly even if you don't).
There's no way to distinguish the standard vector class and the vendor's
vector class.


* With namespaces and "using namespace std":

While a line like

  vector<double> x;

is still ambiguous, you can choose explicitly

::vector<double> x;

or

  std::vector<double> x;

However, you don't need to write

  std::cout << x[10];

since there's only one cout object in there anyway. Instead you can
write

  cout << x[10];


* With namespaces, but without using:

You have to prefix *every* std library symbol with "std::". This
gives more work for the moment, but may save some work in case a later
library change adds a new name that clashes with a std library name.
However, since the compiler catches such problems on compile, I'd
view the change when needed as the simpler alternative, especially
since such a name clash is unlikely anyway, and since even if it occurs,
the work is still less since the std:: prefix must be put in front
of only the conflicting names, instead of all names, and the places
are well told from the compiler (it could even be automated using
the compiler output).
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: source@netcom.com (David Harmon)
Date: 1998/09/07
Raw View
On 5 Sep 1998 23:46:31 GMT, "P.J. Plauger" <pjp@dinkumware.com> wrote:

>> Everyone seems to say that a global "using namespace std" is a
>> bad thing,
>
>Not everyone. I don't. But then...

"using namespace std" apparently discards any advantage that might be
gained by having namespace std in the first place.  Do you feel, then,
that namespace std was a mistake?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/09/07
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote:
>Nathan Myers <ncm@nospam.cantrip.org> writes
>>
>>The list in the quoted "Note:" is of names that (unusually) are
>>all lower-case.  All the other macros are upper-case.  If you stay
>>away from the listed names and upper-case names, you can avoid
>>colliding with macros in C++ headers.
>
>So how do we kill the style that advocates such things as:
>  const double PI = 3.1415926;
>or
>  enum Bool {FALSE, TRUE};

Education and good coding standards.

>I am certain that this style is based on a misunderstanding as to why
>manifest constants are written all upper case in C.

I hope that those who write introductory books and articles can be
persuaded to observe some discipline in their own examples.

--
Nathan Myers
ncm@nospam.cantrip.org  http://www.cantrip.org/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Michel Michaud" <Michel.Michaud@sympatico.ca>
Date: 1998/09/05
Raw View
I just recently found out that, in VC5, I can include ctime, cmath, etc. and
use their functions or types without the std prefix (in fact it is not even
recognized). I supposed this is a bug, but for a moment I had this question
in mind: do the standard say that standard identifiers are in the std
namespace? If so there could be no macro because they don't work with
namespace. I read what I have (CD2) and found (17.3.1.1 and 17.3.1.2) that
it is not clear if, for example, NULL is std::NULL. Also std::errno could be
wrong or IS wrong... surprising!

Everyone seems to say that a global "using namespace std" is a
bad thing, but how can we do otherwise if we don't know if an
identifier is in std or not (could even change from one compiler
to the other, if I read correctly)? I guess we could even say that
we need to declare std just in case :

#include <ctime> // maybe I'm not sure namespace std is declared
namespace std {} // so I declare it before the using
using namespace std;

Maybe there is a real list of the macros of C, in CD2 we have :

[Note:  the  names  defined as macros in C include  the
following:  assert,  errno,  offsetof,  setjmp,  va_arg,
va_end, and va_start.   --end note]

NULL and EOF are not mentioned... We would have to remember the
list because those would be the ones where std:: should not be
used. But I am alone in finding this very odd?

Michel Michaud micm19@removethis.mail2.cstjean.qc.ca
http://www3.sympatico.ca/michel.michaud




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






Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/09/05
Raw View
Michel Michaud<Michel.Michaud@sympatico.ca> wrote:
>I just recently found out that, in VC5, I can include ctime, cmath, etc.
>and use their functions or types without the std prefix (in fact it is
>not even recognized). I supposed this is a bug,

It is.

>... but for a moment I had this question
>in mind: do the standard say that standard identifiers are in the std
>namespace?

Yes.

>If so there could be no macro because they don't work with
>namespace. I read what I have (CD2) and found (17.3.1.1 and 17.3.1.2) that
>it is not clear if, for example, NULL is std::NULL. Also std::errno could be
>wrong or IS wrong... surprising!

The standard is clear.  Whatever is defined to be a macro in C is
a macro in C++.  This includes NULL and EOF.  With one exception,
anything *not* defined to be a macro in C is in fact not a macro
in C++.  The exception is "errno", which in C may be a macro or not,
but in C++ is required to be a macro.

>Everyone seems to say that a global "using namespace std" is a
>bad thing, but how can we do otherwise if we don't know if an
>identifier is in std or not (could even change from one compiler
>to the other, if I read correctly)?

The standard is clear.  Of course, buggy compilers are sold, and
sometimes you have to work around their bugs.  It's best minimize
pollution of your code with such workarounds.  Adding "using namespace
std;" is *not* minimal pollution.

>I guess we could even say that
>we need to declare std just in case :
>
># include <ctime> // maybe I'm not sure namespace std is declared
>  namespace std {} // so I declare it before the using
>  using namespace std;
>
>Maybe there is a real list of the macros of C, in CD2 we have :
>
>[Note:  the  names  defined as macros in C include  the
>following:  assert,  errno,  offsetof,  setjmp,  va_arg,
>va_end, and va_start.   --end note]
>
>NULL and EOF are not mentioned... We would have to remember the
>list because those would be the ones where std:: should not be
>used.

The list in the quoted "Note:" is of names that (unusually) are
all lower-case.  All the other macros are upper-case.  If you stay
away from the listed names and upper-case names, you can avoid
colliding with macros in C++ headers.

> But I am alone in finding this very odd?

It is unfortunate that the C standard defined lower-case macros, so
that C++ was obliged to match them.  Anyway, the list is pretty short.
Note that is is very rare in C++ to actually need to use most of those
names, "assert" excepted.

--
Nathan Myers
ncm@nospam.cantrip.org  http://www.cantrip.org/



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






Author: "P.J. Plauger" <pjp@dinkumware.com>
Date: 1998/09/05
Raw View
Michel Michaud <Michel.Michaud@sympatico.ca> wrote in article <01bdd85b$a7423700$bbe3acce@b1gyin27>...
>
> I just recently found out that, in VC5, I can include ctime, cmath, etc. and
> use their functions or types without the std prefix (in fact it is not even
> recognized). I supposed this is a bug,

No, it was intentional. At the time VC++ V5.0 froze, there was still serious
debate about how to meld the Standard C library with the newly introduced
concept of namespace std in the draft Standard C++ library. The debate
continued right up to the meeting in November 1997 at which the draft finally
froze. Given the state of the final draft (FDIS), it is clear that VC++ will have
to change to better conform. But there is still more than one school of thought
on how best to change it.

>                                                           but for a moment I had this question
> in mind: do the standard say that standard identifiers are in the std
> namespace?

Those declared in the Standard C++ library, yes.

>                    If so there could be no macro because they don't work with
> namespace.

It is true that the Standard C library, when it serves as part of the Standard C++
library, cannot mask library functions with macros. (Only the signatures are
reserved, not the function names as in C.) But a number of macros remain, and
these cannot be confined to a namespace, as you observe.

>                       I read what I have (CD2) and found (17.3.1.1 and 17.3.1.2) that
> it is not clear if, for example, NULL is std::NULL. Also std::errno could be
> wrong or IS wrong... surprising!

Uh huh. This was one of the arguments against ``fixing'' the Standard C
library by wrapping it inside namespace std.

> Everyone seems to say that a global "using namespace std" is a
> bad thing,

Not everyone. I don't. But then...

>                 but how can we do otherwise if we don't know if an
> identifier is in std or not (could even change from one compiler
> to the other, if I read correctly)? I guess we could even say that
> we need to declare std just in case :
>
> #include <ctime> // maybe I'm not sure namespace std is declared
> namespace std {} // so I declare it before the using
> using namespace std;

Yes, I often do this in testing code that I want to be highly portable
across existing implementations.

> Maybe there is a real list of the macros of C, in CD2 we have :
>
> [Note:  the  names  defined as macros in C include  the
> following:  assert,  errno,  offsetof,  setjmp,  va_arg,
> va_end, and va_start.   --end note]
>
> NULL and EOF are not mentioned... We would have to remember the
> list because those would be the ones where std:: should not be
> used. But I am alone in finding this very odd?

No.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com/hot_news.html



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






Author: mw@ipx2.rz.uni-mannheim.de (Marc Wachowitz)
Date: 1998/09/06
Raw View
"Michel Michaud" <Michel.Michaud@sympatico.ca> wrote:
> I just recently found out that, in VC5, I can include ctime, cmath, etc. and
> use their functions or types without the std prefix (in fact it is not even
> recognized).

I don't have access to VC5 now, and perhaps you did already try this, but
just in case there's _also_ a real function, which is merely shadowed by
the macro: If you put the function's name within parantheses, it won't
be matched by a function-like macro (one with parantheses, even if these
might not include any arguments, simulating a function without arguments);
i.e. (function_name)(args) or (std::function_name)(args) would work if
there is some function available. Of course, then you could as well write
#undef function_name
to get rid of the macro, and thus refer to the function normally. A function
would be needed anyway if you're supposed to be able to take the address
of the standard function, even in C, thus it's not unlikely that a function
is available, too. That one may or may not properly be in namespace std;
you'll have to find out.

> Everyone seems to say that a global "using namespace std" is a
> bad thing, but how can we do otherwise if we don't know if an
> identifier is in std or not (could even change from one compiler
> to the other, if I read correctly)?

Below is an approach which should work with almost every C++ compiler, if
it does support namespaces, but where perhaps some functions aren't yet in
namespace std, and may not even be proper functions (if there are just
superfluous macros, but still functions available in std, simply #undef
these, as mentioned above). I'm writing "almost" since strictly speaking,
as far as I know, you aren't really supposed to #define (or perhaps even
declare - I don't know this for sure) anything at all before including the
standard headers, even if your names don't conflict with anything reserved
by/for the standard or implementation. However, I guess this won't cause
any problems in practice, if you chose your names sufficiently "exotic" to
remain unused for anything by an implementation (e.g. use some good prefix;
I'm using FOO or foo for that case in the example below, though you should
probably use something else, given that this word is somewhat famous to mean
something arbitrary, and a bad implementor may grab it somewhere). The goal
of this approach is to restrict adaption for such faulty implementations
to a few central places, and do this in a way such that (except for the
caveat mentioned above) the main code works with various implementations,
and all traces of those fixes can be automatically removed, once you don't
expect such problems any more (well, one can always hope ;-).

Assume that each implementation can be recognized by the presence of some
macro, which I'll call __impl below; replace that by the appropriate name,
which may either be defined implicitly by the compiler, or which you may
define by some other means (e.g. some compiler switch, or if that isn't
possible, by always including some file which is changed for compilation
with the respetive implementation, containing an explicit #define __impl).
For the example, let's say there's a standard function matching prototype
int some_function(int);
which is only provided as macro, or as a function outside of any namespace,
but which should really be a function in namespace std.

In your normal application code, instead of

#include <some_standard_header>

write

#include "foo_some_standard_header.h" // don't duplicate the .h if present

and then refer to std::some_function, just as you would have done with a
conforming implementation.

If you fear that some other macro provided by the implementation - for
which you don't want to (or cannot) provide a wrapper as below - may use
that faulty macro, you might  keep the macro available (no #undef) and
write (std::some_function) instead. Of course, then you'll also have to
write (some_other_namespace::some_function) if you want to use the name in
some_other_namespace, even in its definition there. I'd try to avoid it.

As far as I can tell, if the implementation even defines the macro without
any parantheses, you don't have any chance to both keep the macro and refer
to the proper function in one source region; you must #undef some_function
before you can refer to it as something other than the macro. However, I
expect such an extreme case to be quite rare for a standard function name.

//---------------------------------------------------------------------------
// file "foo_some_standard_header.h", wrapper for <foo_some_standard_header>
#ifndef FOO_some_standard_header_INCLUDED
#define FOO_some_standard_header_INCLUDED
#include <some_standard_header>
#ifdef __impl
#ifndef FOO_some_standard_header_IMPLEMENTATION
#undef some_function
#endif // FOO_some_standard_header_IMPLEMENTATION
namespace std {
  int (some_function)(int);
}
#endif // __impl
// similarly for other implementations/problems, maybe merging common stuff
#endif // FOO_some_standard_header_INCLUDED

//---------------------------------------------------------------------------
// file "foo_some_standard_header.cxx", implementing the wrapper function(s)
#define FOO_some_standard_header_IMPLEMENTATION
#include "foo_some_standard_header.h"

#ifdef __impl
namespace {
  // This is not in namespace std, just to ensure that the call below will
  // not cause recursion, independently of any top-level definition for
  // the name some_function. If anonymous namespaces don't work, it could
  // as well be defined as static.
  inline int foo_std_alias_some_function(int foo_arg)
    {
      return some_function(foo_arg); // we want the macro if there is one!
    }
}

#undef some_function  // in case of non-function-like macro

int (std::some_function)(int foo_arg) // this is the wrapper function
{
  return foo_std_alias_some_function(foo_arg);
}
#endif // __impl
// ... similarly for others

//---------------------------------------------------------------------------

If you don't need a unique address for the redefinition of std::some_function
(or does inline still force the compiler to handle this automatically? I'm
not sure about that right now), and if you can tolerate - or don't need - the
intermediate foo_std_alias_some_function (which you could also place in some
other namespace, say, foo_std_alias), you could as well place it as inline
function directly in the header file "foo_some_standard_header.h". The same
approach should also work for typedef names which aren't in namespace std.

-- Marc Wachowitz <mw@ipx2.rz.uni-mannheim.de>


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






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/06
Raw View
In article <6sse97$hh8$1@shell7.ba.best.com>, Nathan Myers
<ncm@nospam.cantrip.org> writes
>The list in the quoted "Note:" is of names that (unusually) are
>all lower-case.  All the other macros are upper-case.  If you stay
>away from the listed names and upper-case names, you can avoid
>colliding with macros in C++ headers.

So how do we kill the style that advocates such things as:

const double PI = 3.1415926;
or
enum Bool {FALSE, TRUE};

I am certain that this style is based on a misunderstanding as to why
manifest constants are written all upper case in C.

--
Francis Glassborow


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