Topic: issue with namespaces and operator lookup


Author: andys@evo6.com.NoSpam (Andy Sawyer)
Date: Sun, 27 Oct 2002 22:39:09 +0000 (UTC)
Raw View
In article <ap8pk0$s5m3t$1@ID-48580.news.dfncis.de>,
 on Sat, 26 Oct 2002 22:56:25 +0000 (UTC),
 pcarlini@unitus.it (Paolo Carlini) wrote:

> James Kanze wrote:
>
> >And the solution of defining the operator in std:: isn't legal either.
> >The only thing you're allowed to add to std:: are specializations for
> >types YOU'VE defined.
> >
> Thanks, in particualar for this punctualization.
>
> Could you possibly point me to the relevant section of the standard?

,----[ 17.4.3.1, Reserved names. ]
| 1 It is undefined for a C++ program to add declarations or definitions
|   to namespace std or namespaces within namespace std unless otherwise
|   specified. A program may add template specializations for any
|   standard library template to namespace std. Such a specialization
|   (complete or partial) of a standard library template results in
|   undefined behavior unless the declaration depends on a user-defined
|   name of external linkage and unless the specialization meets the
|   standard library requirements for the original template.
`----

Regards,
 Andy S.
--
"Light thinks it travels faster than anything but it is wrong. No matter
 how fast light travels it finds the darkness has always got there first,
 and is waiting for it."                  -- Terry Pratchett, Reaper Man

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 23 Oct 2002 16:24:17 +0000 (UTC)
Raw View
jbuck@synopsys.com (Joe Buck) wrote in message
news:<200210211632.g9LGWwf16900@piper.synopsys.com>...
> Consider the following program, for counting words and producing a
> frequency count:

> -------------------------------------------------------------
> #include <iostream>
> #include <string>
> #include <algorithm>
> #include <iterator>
> #include <map>
> #include <vector>

> typedef std::map<std::string,unsigned> Maptype;
> typedef std::pair<std::string,unsigned> Pairtype;

> class Ordering {
> public:
>   bool operator()(const Pairtype& a, const Pairtype& b) const {
>     if (a.second != b.second)
>       return a.second < b.second;
>     return a.first < b.first;
>   }
> };

> inline std::ostream& operator<<(std::ostream& o, const Pairtype& a) {
>   o << a.first << ": " << a.second;
>   return o;
> }

> int main()
> {
>   Maptype word_count;
>   std::string word;
>   while (std::cin >> word)
>     word_count[word] += 1;
>   std::vector<Pairtype> data(word_count.begin(), word_count.end());
>   std::sort(data.begin(), data.end(), Ordering());
> #ifdef HIDE_THE_ISSUE
>   for (std::vector<Pairtype>::const_iterator p = data.begin(); p != data.end(); ++p)
>     std::cout << (*p) << std::endl;
> #else
>   std::copy(data.begin(), data.end(),
>      std::ostream_iterator<Pairtype>(std::cout, "\n"));
> #endif
> }
> -------------------------------------------------------------

> If HIDE_THE_ISSUE is not defined, recent gcc and Intel compilers
> reject the program; in the expansion of the ostream_iterator template,
> the operator<< is not found.  If HIDE_THE_ISSUE is defined, the direct
> calls to the << operator match, and the program compiles and runs.

> The argument for not accepting the program in the former case goes
> something like this: std::ostream_iterator is in std, as are the two
> arguments to the << operator in the expansion (the std::ostream and
> the std::pair<std::string,unsigned>), so we only look in std:: for
> matches; Koenig lookup will not "pull in" names from other namespaces.
> But I had thought that the global namespace was always visible, and
> the Koenig lookup rule only addresses names from namespaces not
> currently "pulled in".

> And yes, if we modify the program to

> namespace std {
>   inline std::ostream& operator<<(std::ostream& o, const Pairtype& a) {
>     o << a.first << ": " << a.second;
>     return o;
>   }
> }

> it is accepted.

> Comments?  Verdict?

Just another thing the standard broke.  They changed the rules during
standardization, and your previously correct program is now incorrect;
roughly speaking, type dependant name lookup only uses Koenig lookup.

If you have to deal with a real problem of this nature, check what
compiler options are available.  Any reasonable compiler will offer
options to use the old name look-up -- breaking working user code is
about the worse sin a compiler can do.  For the future, however, you're
stuck.

And the solution of defining the operator in std:: isn't legal either.
The only thing you're allowed to add to std:: are specializations for
types YOU'VE defined.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Wed, 23 Oct 2002 16:57:37 +0000 (UTC)
Raw View
I still think we should allow writing

   let p = data.begin()

instead of having to write

   std::vector<Pairtype>::const_iterator p = data.begin()



    John Nagle
    Animats





James Kanze wrote:

> jbuck@synopsys.com (Joe Buck) wrote in message
> news:<200210211632.g9LGWwf16900@piper.synopsys.com>...
>
>>Consider the following program, for counting words and producing a
>>frequency count:

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pcarlini@unitus.it (Paolo Carlini)
Date: Sat, 26 Oct 2002 22:56:25 +0000 (UTC)
Raw View
James Kanze wrote:

>And the solution of defining the operator in std:: isn't legal either.
>The only thing you're allowed to add to std:: are specializations for
>types YOU'VE defined.
>
Thanks, in particualar for this punctualization.

Could you possibly point me to the relevant section of the standard?

Ciao, Paolo.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jbuck@synopsys.com (Joe Buck)
Date: Mon, 21 Oct 2002 23:04:32 +0000 (UTC)
Raw View
Consider the following program, for counting words and producing a frequency
count:

-------------------------------------------------------------
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <map>
#include <vector>

typedef std::map<std::string,unsigned> Maptype;
typedef std::pair<std::string,unsigned> Pairtype;

class Ordering {
public:
  bool operator()(const Pairtype& a, const Pairtype& b) const {
    if (a.second != b.second)
      return a.second < b.second;
    return a.first < b.first;
  }
};

inline std::ostream& operator<<(std::ostream& o, const Pairtype& a) {
  o << a.first << ": " << a.second;
  return o;
}

int main()
{
  Maptype word_count;
  std::string word;
  while (std::cin >> word)
    word_count[word] += 1;
  std::vector<Pairtype> data(word_count.begin(), word_count.end());
  std::sort(data.begin(), data.end(), Ordering());
#ifdef HIDE_THE_ISSUE
  for (std::vector<Pairtype>::const_iterator p = data.begin(); p != data.end(); ++p)
    std::cout << (*p) << std::endl;
#else
  std::copy(data.begin(), data.end(),
     std::ostream_iterator<Pairtype>(std::cout, "\n"));
#endif
}
-------------------------------------------------------------

If HIDE_THE_ISSUE is not defined, recent gcc and Intel compilers reject
the program; in the expansion of the ostream_iterator template, the
operator<< is not found.  If HIDE_THE_ISSUE is defined, the direct calls
to the << operator match, and the program compiles and runs.

The argument for not accepting the program in the former case goes
something like this: std::ostream_iterator is in std, as are the two
arguments to the << operator in the expansion (the std::ostream and the
std::pair<std::string,unsigned>), so we only look in std:: for matches;
Koenig lookup will not "pull in" names from other namespaces.  But I
had thought that the global namespace was always visible, and the Koenig
lookup rule only addresses names from namespaces not currently "pulled in".

And yes, if we modify the program to

namespace std {
  inline std::ostream& operator<<(std::ostream& o, const Pairtype& a) {
    o << a.first << ": " << a.second;
    return o;
  }
}

it is accepted.

Comments?  Verdict?

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: vAbazarov@dAnai.com ("Victor Bazarov")
Date: Tue, 22 Oct 2002 04:55:13 +0000 (UTC)
Raw View
"Joe Buck" <jbuck@synopsys.com> wrote...
> Consider the following program, for counting words and producing a
frequency
> count:
>
> -------------------------------------------------------------
> #include <iostream>
> #include <string>
> #include <algorithm>
> #include <iterator>
> #include <map>
> #include <vector>
>
> typedef std::map<std::string,unsigned> Maptype;
> typedef std::pair<std::string,unsigned> Pairtype;
>
> class Ordering {
> public:
>   bool operator()(const Pairtype& a, const Pairtype& b) const {
>     if (a.second != b.second)
>       return a.second < b.second;
>     return a.first < b.first;
>   }
> };
>
> inline std::ostream& operator<<(std::ostream& o, const Pairtype& a) {
>   o << a.first << ": " << a.second;
>   return o;
> }
>
> int main()
> {
>   Maptype word_count;
>   std::string word;
>   while (std::cin >> word)
>     word_count[word] += 1;
>   std::vector<Pairtype> data(word_count.begin(), word_count.end());
>   std::sort(data.begin(), data.end(), Ordering());
> #ifdef HIDE_THE_ISSUE
>   for (std::vector<Pairtype>::const_iterator p = data.begin(); p !=
data.end(); ++p)
>     std::cout << (*p) << std::endl;
> #else
>   std::copy(data.begin(), data.end(),
>     std::ostream_iterator<Pairtype>(std::cout, "\n"));
> #endif
> }
> -------------------------------------------------------------
>
> If HIDE_THE_ISSUE is not defined, recent gcc and Intel compilers reject
> the program; in the expansion of the ostream_iterator template, the
> operator<< is not found.  If HIDE_THE_ISSUE is defined, the direct calls
> to the << operator match, and the program compiles and runs.
>
> The argument for not accepting the program in the former case goes
> something like this: std::ostream_iterator is in std, as are the two
> arguments to the << operator in the expansion (the std::ostream and the
> std::pair<std::string,unsigned>), so we only look in std:: for matches;
> Koenig lookup will not "pull in" names from other namespaces.  But I
> had thought that the global namespace was always visible, and the Koenig
> lookup rule only addresses names from namespaces not currently "pulled
in".

You had thought incorrectly.  It only considers the namespaces where
the types of arguments are defined.  See 3.4.2/2, "If T is a class..".
There is nothing about global namespace.

>
> And yes, if we modify the program to
>
> namespace std {
>   inline std::ostream& operator<<(std::ostream& o, const Pairtype& a) {
>     o << a.first << ": " << a.second;
>     return o;
>   }
> }
>
> it is accepted.
>
> Comments?  Verdict?

Well, the Koenig lookup IMHO implemented in those compilers
correctly.

Victor
--
Please remove capital A's from my address when replying by 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://www.jamesd.demon.co.uk/csc/faq.html                       ]