Topic: namespace and operator question


Author: zalman@netcom.com (Zalman Stern)
Date: 1998/10/16
Raw View
darin@spies.com wrote:
: I wrote this small source file to test a problem with the compiler I use most
: often (Metrowerks CodeWarrior):

:     #include <numeric>
:     #include <vector>
:     namespace N { class C { }; }
:     typedef N::C T;
:     std::vector<T> v;
:     int operator +(int i, T);
:     int test() { return std::accumulate(v.begin(), v.end(), 0); }

: The program doesn't compile, presumably because it can't find the operator +
: which is in the global namespace.

The problem is that it finds something else first. You can verify this by
snagging the decl of accumulate out of numeric and declaring it in your own
namespace. Then use "my_namespace::accumulate" instead of the one in std::
. The error goes away. If you preprocess the above code snippet and search
for "operator[ ]*\+[^+]" (replace caret with option-L if need be) you will
will see a few templates declaring operator+ and a whole slew of inline
friend functions declaring operator+ within various classes. If you #if 0
all of those, the sample compiles.

Is this conforming? I don't know. The standard does not specify the friend
functions in class vector expclitly so I assume they are a side effect of
the Metrowerks Standard Library implementation. (I'm not sure whether the
standard specifies the templates for operator+ which are "freestanding" in
namespace std:: . I doubt it though.)

-Z-
---
[ 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/10/16
Raw View
<darin@spies.com> wrote:
>I wrote this small source file to test a problem with the compiler I use
>most often (Metrowerks CodeWarrior):
>
>    #include <numeric>
>    #include <vector>
>    namespace N { class C { }; }
>    typedef N::C T;
>    std::vector<T> v;
>    int operator +(int i, T);
>    int test() { return std::accumulate(v.begin(), v.end(), 0); }
>
>The program doesn't compile, presumably because it can't find the operator +
>which is in the global namespace. The vendor claims that this behavior is
>correct and above program should fail to compile under any C++ compiler. The
>following program will work correctly, presumably due to the Koenig rule:
> [ version of above with operator+ declared in namespace N ]

Metrowerks is correct.  The compiler tries to look up operator+ two ways:

1. starting from within std:: (because that's where std:: is defined)
   and continuing outward if it doesn't find any, and

2. within N (because that's where C is defined) but not continuing outward.

Whatever it finds gets overloaded.

It doesn't find any operators+ in N::, but it finds plenty of operators+
in std::, such as for the iterators.  (Probably the <vector> header
sub-includes <iterator>.)  None of the operators+ it finds match, but
they hide the global declaration.

The Egcs-1.1 compiler exhibits the same behavior when presented
the same namespaces.  Edg-2.38 does not.  (I haven't tried Edg-2.39.)

--
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: darin@spies.com
Date: 1998/10/17
Raw View
In article <zalmanF0wKL6.n0H@netcom.com>,
  Zalman Stern <zalman@netcom.com> wrote:

> Darin Adler <darin@spies.com> wrote:
> : I wrote this small source file to test a problem with the compiler
> : I use most often (Metrowerks CodeWarrior):
> :
> :     #include <numeric>
> :     #include <vector>
> :     namespace N { class C { }; }
> :     typedef N::C T;
> :     std::vector<T> v;
> :     int operator +(int i, T);
> :     int test() { return std::accumulate(v.begin(), v.end(), 0); }
> :
> : The program doesn't compile, presumably because it can't find the operator +
> : which is in the global namespace.

> The problem is that it finds something else first. You can verify this by
> snagging the decl of accumulate out of numeric and declaring it in your own
> namespace. Then use "my_namespace::accumulate" instead of the one in std::
> . The error goes away. If you preprocess the above code snippet and search
> for "operator[ ]*\+[^+]" (replace caret with option-L if need be) you will
> will see a few templates declaring operator+ and a whole slew of inline
> friend functions declaring operator+ within various classes. If you #if 0
> all of those, the sample compiles.
>
> Is this conforming? I don't know. The standard does not specify the friend
> functions in class vector expclitly so I assume they are a side effect of
> the Metrowerks Standard Library implementation. (I'm not sure whether the
> standard specifies the templates for operator+ which are "freestanding" in
> namespace std:: . I doubt it though.)

I got a different answer from Neil Gafter through Herb Sutter.

He said that the call inside std::accumulate is equivalent to a function call
according to 5/2 in current standard draft, with the details of that operation
in 13.3.1.2.

The draft mentions how candidate functions for the function call are collected
in 13.3.1.2/3, which refers to the lookup rules in 3.4.2.

In 3.4.2/2, just before the example, the standard describes how functions
found using "ordinary unqualified lookup" are included as candidates.
According to Neil, the operator+ in the global namespace is something that
would be found by "oridinary unqualified lookup".

Further comments?

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ 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/10/19
Raw View
<darin@spies.com> wrote:
>Zalman Stern <zalman@netcom.com> wrote:
>> Darin Adler <darin@spies.com> wrote:
>> : I wrote this small source file to test a problem with the compiler
>> : I use most often (Metrowerks CodeWarrior):
>> :
>> :     #include <numeric>
>> :     #include <vector>
>> :     namespace N { class C { }; }
>> :     typedef N::C T;
>> :     std::vector<T> v;
>> :     int operator +(int i, T);
>> :     int test() { return std::accumulate(v.begin(), v.end(), 0); }
>> :
>> : The program doesn't compile, presumably because it can't find
>> : the operator+ which is in the global namespace.
>>
>> The problem is that it finds something else first.

>I got a different answer from Neil Gafter through Herb Sutter.

>He said that the call inside std::accumulate is equivalent to a function call
>according to 5/2 in current standard draft, with the details of that operation
>in 13.3.1.2.

>The draft mentions how candidate functions for the function call are collected
>in 13.3.1.2/3, which refers to the lookup rules in 3.4.2.

>In 3.4.2/2, just before the example, the standard describes how functions
>found using "ordinary unqualified lookup" are included as candidates.
>According to Neil, the operator+ in the global namespace is something that
>would be found by "oridinary unqualified lookup".

The question as put to Neil neglected to mention the operators+
also declared in std, which hide the global operator+.

Really this isn't a question about Koenig lookup; Koenig lookup
is the solution to what would otherwise be a serious problem.
This is the ordinary "names in inner scopes hide names in
outer scopes" rule, where the scopes here are the global and std
namespaces.  For the more familiar case of derived classes:

  struct A {
    void f(A&);
  };
  struct B : A {
    void f(B&) { A a; f(a); }
  };

The call to f in B finds B::f, and doesn't look any further,
so it's an error.  You're used to this.

So what's wrong with the original example?  Now that all the std
components are really in the std namespace, things that used to
overload with your own global names now don't.  If you want
std algorithms to find your overloadings, you have to put them
where the compiler can find them using Koenig lookup.

--
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: darin@spies.com
Date: 1998/10/15
Raw View
I wrote this small source file to test a problem with the compiler I use most
often (Metrowerks CodeWarrior):

    #include <numeric>
    #include <vector>
    namespace N { class C { }; }
    typedef N::C T;
    std::vector<T> v;
    int operator +(int i, T);
    int test() { return std::accumulate(v.begin(), v.end(), 0); }

The program doesn't compile, presumably because it can't find the operator +
which is in the global namespace. The vendor claims that this behavior is
correct and above program should fail to compile under any C++ compiler. The
following program will work correctly, presumably due to the Koenig rule:

    #include <numeric>
    #include <vector>
    namespace N {
        class C { };
        int operator +(int i, C);
    }
    typedef N::C T;
    std::vector<T> v;
    int test() { return std::accumulate(v.begin(), v.end(), 0); }

Is the first example incorrect as my vendor claims, or is this a mistake in
their compiler? Any established test that I can use to help convince them it's
an error?

Darin Adler

PS: I'm aware that the program as it stands doesn't do anything useful.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


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