From -9096235750251653241
X-Google-Language: ENGLISH,ASCII
X-Google-Thread: f78e5,e5c2db50725662d
X-Google-Attributes: gidf78e5,public
From: Joerg Barfurth <jbarfurth@vossnet.de>
Subject: Re: Problem with using typedef in a namespace
Date: 1999/05/07
Message-ID: <37321825.7EFA9645@vossnet.de>#1/1
X-Deja-AN: 474965679
X-NNTP-Posting-Host: dialup79.hh.vossnet.de
Content-Transfer-Encoding: 8bit
Approved: stephen.clamage@sun.com (comp.std.c++)
References: <925941289.21893.0.nnrp-01.9e98df50@news.demon.co.uk>
X-UID: 0000000001
X-Status: $$$T
Content-Type: text/plain; charset=iso-8859-1
X-Complaints-To: abuse@vossnet.de
X-Trace: news.vossnet.de 926029808 22149 212.53.199.79 (6 May 1999 22:30:08 GMT)
Organization: DIE BARFURTHS
Mime-Version: 1.0
Reply-To: jbarfurth@vossnet.de
NNTP-Posting-Date: 6 May 1999 22:30:08 GMT
Newsgroups: comp.std.c++
X-MIME-Autoconverted: from quoted-printable to 8bit by ha2mpka.eng.sun.com id PAA21187
Originator: clamage@taumet


Kit Smithers wrote:
> 
> I'm having trouble understanding why the following code produces different
> results.
> 
> It fails under g++ and vc++ although with slightly different errors. The
> problem as I see it is that making a typedef in a namespace to a class
> defined in the global namespace does not behave the same as a typedef to a
> class in the same namespace. Not that there's any reason that it should. But
> it makes seemingly identical function definitions produce different results.

The typedefs behave identical. But still one (class-)type is defined in that
namespace, while the other is defined in global namespace. For elaboration,
see below.

> Here's the code... the line that fails is near the end I've included a
> comment with the error g++ gives.
> 
> #include <string>
> 
> class Byte_Stream_GLOBAL {};
> 
> namespace CSS {
> 
> class Byte_Stream_CSS {};
> 
> typedef Byte_Stream_GLOBAL ByteStreamG;
> typedef Byte_Stream_CSS    ByteStreamC;
> 
> ByteStreamG& operator<<(ByteStreamG& into, const std::string& s);
> ByteStreamC& operator<<(ByteStreamC& into, const std::string& s);
> 
> }
> 
> namespace ABC {
> 
> void myFunc(void)
> {
>     CSS::ByteStreamG gstream;
>     CSS::ByteStreamC cstream;
> 
>     std::string mystring = "hello world";
> 
>     cstream << mystring;
>     gstream << mystring;  // This line produces an error
>  /*
>  nameclash.cxx: In function `void myFunc()':
> nameclash.cxx:35: no match for `::CSS::ByteStreamG & << string &'

It is correct, to see an error here, but this error message is IMHO
misleading: 
The match needed is for ::Byte_Stream_GLOBAL & << ::std::string &.
A typedef name is just another name for a type (i.e it doesn't introduce a new
type. So the type of gstream actually is ::Byte_Stream_Global (see [7.1.3]
p.1). This should already be a hint at what's going on.

> C:\\CYGNUS\\CYGWIN~1\\H-I586~1\\BIN\\..\\lib\\gcc-lib\\i586-cygwin32\\egcs-2
> .91.
> 57\\..\\..\\..\\..\\..\\include\\g++\\std/bastring.cc:469: candidates are:
> opera
> tor <<<char, string_char_traits<char>, alloc>(ostream &, const
> basic_string<char
> ,string_char_traits<char>,__default_alloc_template<false,0> > &)
>      */
> }
> 
> }
> 
> The "work around"  - as in a work around my ignorance is to define the
> function outside of the namespace as in:
> 
> CSS::ByteStreamG& operator<<(CSS::ByteStreamG& into, const std::string& s);

As you don't define "CSS::ByteStreamG& CSS::operator<<(CSS::ByteStreamG& into,
const std::string& s)" (actually you only show a declaration), this
declaration introduces a second operator function with this signature. 
This declaration is not related to the one in namespace CSS (except that they
might clash when resolving overloads where both are in scope).

> Which the compiler finds acceptable.
Fine

> Can anyone give me an indication -- or which bit of the standard I should
> read -- as to what's going on?

In namespace ABC (and thereby in myFunc) both operators from namespace CSS
can't be found by unqualified name lookup, nor are they explicitly qualified
in your code (you can't write gstream CSS::<< mystring anyways). So if any of
them can still be found, it has to be by argument dependent (or 'Koenig') name
lookup. Basically this means that, in addition to the local scope, the
namespaces where the arguments' types are defined are also searched for
matching 'candidate' function declarations. 
This is covered in the standard in section 4.3.2 [basic.lookup.koenig]. In
paragraph 2 it reads:
"For each argument type T in the function call, there is a set of zero or more
associated namespaces [...] to be considered. The set of namespaces [...] is
determined entirely by the types of the function arguments (...). TYPEDEF
NAMES [...] DO NOT CONTIBUTE TO THIS SET." (emphasis added by me).
This is in accordance with the semantics of typedef mentioned above (referring
to 7.1.3).

By this token, Koenig lookup finds CSS::operator<<(...) for
CSS::Byte_Stream_CSS (aka CSS::ByteStreamC), but not for ::Byte_Stream_GLOBAL
(aka CSS::ByteStreamG). Any operator<< declared at global scope (or in
namespace ::std, if ::std::string is the other argument's type) will be
considered as candidate functions for overload resolution (see [13.3.1]) in
the latter case.

HTH
-- J�rg Barfurth


[ 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              ]




