Topic: namespaces and overloading


Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/09/22
Raw View
Nathan Myers wrote:

[...]

> To get the same overloading in definitions of class members, you must
> use an inline function, because a using-declaration is a class body
> can only mention base-class members.
>
>   void f(int);
>   struct A {
>     void f(A const&) { f(0); f(A()); }             // error, A::f hides ::f
>   };
>   struct B {
>     void f(B const&) { using ::f; f(0); f(B()); }  // error, 'using' hides B::f
>   };
>   struct C {
>     static void f(int i) { ::f(i); }
>     void f(C const&) { f(0); f(C()); }             // OK
>   };

What about:

struct D
{
  void f(D const&) { using ::f; using D::f; f(0); f(D()); }
};

BTW, is there a reason why a using-declaration in a class body may
not mention a namespace member?


[ 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/22
Raw View
 Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
>
>Nathan Myers wrote:
>
>[...]
>
>> To get the same overloading in definitions of class members, you must
>> use an inline function, because a using-declaration is a class body
>> can only mention base-class members.
>>   ...
>>   struct C {
>>     static void f(int i) { ::f(i); }
>>     void f(C const&) { f(0); f(C()); }             // OK
>>   };
>
>What about:
>
>struct D
>{
>  void f(D const&) { using ::f; using D::f; f(0); f(D()); }
>};

Here's what EDG-2.38 says (oddly):

  error: a class-qualified name is not allowed

In fact, *only* a class-qualified name is allowed, just not that class.
Egcs-1.1 says, less usefully but more correctly:

  parse error before `::'

>BTW, is there a reason why a using-declaration in a class body may
>not mention a namespace member?

"using" is overloaded in that context.  Probably some other keyword
should have been used, but the two cases are similar enough it would
have caused confusion to have both.

As it is we have renaming facilities for everything except templates,
so generic using-declarations in class bodies are rarely missed.
Perhaps the next revision of the standard will have template typedefs
(or something) to address this problem.

--
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: jarausch@numa1.igpm.rwth-aachen.de (Helmut Jarausch)
Date: 1998/09/18
Raw View
Hi,
please(!) tell me if the following is really true according to the
draft standard.
I have a Vector class which typically overloads many functions from <math.h> by
extending them to Vectors, e.g. 'sqrt'. Typically the function
'Vector sqrt( const Vector& x)'  invokes  'sqrt(x[i])' .

Putting the whole library into its own namespace suddenly hides
'double sqrt(double)' from <math.h> so that overloading (which would use
the 'sqrt' from <math.h>) is not applied.
Replacing 'sqrt' by '::sqrt' or 'std::sqrt' is not an ideal solution.
If I (sometimes) define a 'sqrt' within that class, this version won't
be used and if I overlook that, I have a problem.

As far as I understand, Bjarne Stroustrup's book (3rd ed.) says that
all instances of a function from all visible namespaces should take part
in overload resolution.

What did I miss?

Thanks,
Helmut Jarausch.

--
Helmut Jarausch
Lehrstuhl fuer Numerische Mathematik
Institute of Technology, RWTH Aachen
D 52056 Aachen, Germany


[ 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/18
Raw View
Helmut Jarausch<jarausch@numa1.igpm.rwth-aachen.de> wrote:
>
>I have a Vector class which typically overloads many functions from
><math.h> byextending them to Vectors, e.g. 'sqrt'. Typically the function
>'Vector sqrt( const Vector& x)'  invokes  'sqrt(x[i])' .
>
>Putting the whole library into its own namespace suddenly hides
>'double sqrt(double)' from <math.h> so that overloading (which would use
>the 'sqrt' from <math.h>) is not applied.
>Replacing 'sqrt' by '::sqrt' or 'std::sqrt' is not an ideal solution.
>If I (sometimes) define a 'sqrt' within that class, this version won't
>be used and if I overlook that, I have a problem.
>
>As far as I understand, Bjarne Stroustrup's book (3rd ed.) says that
>all instances of a function from all visible namespaces should take part
>in overload resolution.

This is a good question.

All visible instances of a function take part in overload resolution.
However, when viewed from within the namespace, names in a namespace
*hide* names declared outside it.  To overload them, you can say:

  #include <cmath>
  #include <Vector.h>

  namespace ns {
    using std::sqrt;
    Vector sqrt(Vector const& x)
      { ... sqrt(x[i]) ... }   // OK
  }

To get the same overloading in definitions of class members, you must
use an inline function, because a using-declaration is a class body
can only mention base-class members.

  void f(int);
  struct A {
    void f(A const&) { f(0); f(A()); }             // error, A::f hides ::f
  };
  struct B {
    void f(B const&) { using ::f; f(0); f(B()); }  // error, 'using' hides B::f
  };
  struct C {
    static void f(int i) { ::f(i); }
    void f(C const&) { f(0); f(C()); }             // OK
  };

--
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: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/19
Raw View
In article <6tudq6$fj4$1@shell7.ba.best.com>, Nathan Myers
<ncm@nospam.cantrip.org> writes
>  void f(int);
>  struct A {
>    void f(A const&) { f(0); f(A()); }             // error, A::f hides ::f
>  };
>  struct B {
>    void f(B const&) { using ::f; f(0); f(B()); }  // error, 'using' hides B::f
>  };
>  struct C {
>    static void f(int i) { ::f(i); }
>    void f(C const&) { f(0); f(C()); }             // OK
>  };

However be very careful when writing such forwarding (wrapper)
functions.  The latest rules require copy constructors to be called to
initialise value parameters.  In this case we are using a builtin so
there is no cost but if any parameter has a non-trivial copy constructor
the rules require that it be called each time. So if the i had such a
copy constructor forwarding this way would require two calls to it.
This was one of the things that concerned some of us when the rule was
made explicit.

The solution is to always pass by (usually const reference) to
forwarding functions.  Unfortunately this is also not cost free as it
has potential impact on other optimisations.

Francis Glassborow      Chair of Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ 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: loewis@informatik.hu-berlin.de (Martin von Loewis)
Date: 1998/09/19
Raw View
In article <6tt61u$ff9$1@nets3.rz.RWTH-Aachen.DE>,
Helmut Jarausch <jarausch@numa1.igpm.rwth-aachen.de> wrote:
>Replacing 'sqrt' by '::sqrt' or 'std::sqrt' is not an ideal solution.
>If I (sometimes) define a 'sqrt' within that class, this version won't
>be used and if I overlook that, I have a problem.

Indeed, class members hide namespace members. There is nothing wrong
with that: methods operate on objects, functions operate on arguments.
The real problem here is your naming convention: do not call a member
function 'sqrt' if you want to take advantage of overload resolution
for std::sqrt.

If you do have a class where sqrt is a meaningful function, make it
a friend function.

Regards,
Martin



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