namespaces and function overloading

R

RA Scheltema

Hi all,

I have the following code:

namespace A {
inline void func(int) { ...; }
inline void func(float) { ...; }
inline void func(char) { ...; }
}

namespace B {
inline void func(double) { ...; }

inline myApp()
{
int a;
func(a); // error here
}
}

Which results in the compile-error:
"cannot convert parameter 1 from 'int' to 'double' ...

Which I guess means that all the definitions of func in namespace A are
forgotten in namespace B. Is this something general for c++ or is it
specific for my microsoft visual c++ 6.0 . And more importantly, is there a
work-around / solution ?


thanks ahead,
Richard
 
K

Karl Heinz Buchegger

RA said:
Hi all,

I have the following code:

namespace A {
inline void func(int) { ...; }
inline void func(float) { ...; }
inline void func(char) { ...; }
}

namespace B {
inline void func(double) { ...; }

inline myApp()
{
int a;
func(a); // error here
}
}

Which results in the compile-error:
"cannot convert parameter 1 from 'int' to 'double' ...

Hmm. I don't get this error when compiling the above. And I
use VC++ 6.0
Which I guess means that all the definitions of func in namespace A are
forgotten in namespace B.

No, they are not forgotten. But namespace A is not searched for the
functions
 
R

RA Scheltema

Hmm. I don't get this error when compiling the above. And I
use VC++ 6.0

Hmm, in my project its part of quite a large code-base. Maybe I should have
checked the code :(, however the example is a very stripped down version of
my problem.
No, they are not forgotten. But namespace A is not searched for the
functions

But this means that when a function "func" is found in namespace B it will
only try this one and don't bother with the ones in namespace A ? This would
concur with what I'm finding in my project, since the error does not occur
when I don't define a function "func" in namespace B (in my project that is
....).

I did find the following solution:

using A::func;
namespace B{
....
}


however this results in the error:
"ambiguous call to func ..."

and explicit casting does not solve the problem.


Is there something I'm doing wrong ?


regards,
Richard
 
J

Jonathan Mcdougall

Hmm. I don't get this error when ?
Hmm, in my project its part of quite a
large code-base. Maybe I should have
checked the code :(, however the example
is a very stripped down version of
my problem.

What Karl meant is that conversion from int
to double is legal and you shouldn't have
had an error about it. It may be that your
error was different on the real code, I
think we all understand what you mean.
No, they are not forgotten. But namespace
A is not searched for the functions
But this means that when a function
"func" is found in namespace B it will
only try this one and don't bother with
the ones in namespace A ? This would
concur with what I'm finding in my
project, since the error does not occur
when I don't define a function "func" in
namespace B (in my project that is
...).

This:

namespace A
{
void f();
}

namespace B
{
void g()
{
f(); // error
}
}

is invalid. Namespaces are meant to
prevent name clashing and therefore, it is
by design that function in a namespace are
not available from another, without special
syntax.
I did find the following solution:
using A::func;
namespace B{
...

}

This is one way of doing it.
however this results in the error:
"ambiguous call to func ..."

Where? If it's at namespace scope, this is
weird because in a namespace, local names
will always be preferred to other names.
Therefore, this is valid:

namespace A
{
void f(int) {}
}

using namespace A;
namespace B
{
void f(int) {}

void g()
{
f(10); // ok, calls B::f()
}
}

The problem is in the global scope:

int main()
{
using namespace A;
using namespace B;

f(10); // ambiguous
}
and explicit casting does not solve the
problem.

What casting?
Is there something I'm doing wrong ?

You don't understand namespaces. Read
about them.


Jonathan
 
F

Fraser Ross

"Jonathan Mcdougall"
Where? If it's at namespace scope, this is
weird because in a namespace, local names
will always be preferred to other names.

I find with BCB6 that A::func(double) is called with this test:


namespace A {
inline void func(int) { ; }
inline void func(float) { ; }
inline void func(char) { ; }
inline void func(double) { ; }
}

namespace B {
inline void func(double) { ; }

inline void myApp()
{
using A::func;
//using B::func;
double a;
func(a); // error here
}
}

#pragma argsused
int main(int argc, char* argv[])
{ B::myApp();
return 0;
}
 
J

Jonathan Mcdougall

Where? If it's at namespace scope, this is
I find with BCB6 that A::func(double) is called with this test:

That's not the same thing.
namespace A {
inline void func(int) { ; }
inline void func(float) { ; }
inline void func(char) { ; }
inline void func(double) { ; }
}

namespace B {
inline void func(double) { ; }

inline void myApp()
{
using A::func;
//using B::func;
double a;
func(a); // error here

This should prefer A::func to B::func because you specificaly say it
with 'using A::func'. You should have no error because there is no
ambiguity.

namespace A
{
void f(int);
}

namespace B
{
void f(int);

void g()
{
f(10); // calls B::f

using namespace A;
f(10); // calls B::f (preferred over A::f)

using A::f;
f(10); // calls A::f (because of using)
}
}

int main()
{
f(10); // error, not found

// dump both namespaces here
using namespace A;
using namespace B;

// ambiguous (using both A::f and B::f)
f(10);

// specifically use A::f
using A::f;

// calls A::f
f(10);

// specifically use B::f (this does *not* override
// the previous using declaration)
using B::f;

// ambiguous (using both A::f and B::f)
f(10);
}
}

}

#pragma argsused

Make sure you strip non standard code before posting.
int main(int argc, char* argv[])
{ B::myApp();
return 0;
}
 
F

Fraser Ross

If I want to prefer a swap function written for a class in its namespace
over std:swap I thought I should have a using declaration for std:swap
before the call. So that won't work as I expected.

Fraser.
 
F

Fraser Ross

Instead of a using declaration I want a using directive with minimal code
blocked. I.E:
{
using namespace std;
swap(a1,a2);
}
Argument dependent lookup will link the call to any swap function in the
namespace of the type of a1/a2.

Fraser.
 
J

Jonathan Mcdougall

If I want to prefer a swap function
written for a class in its namespace
over std:swap

You should have no problem if no
using directive is used:

# include <algorithm>

namespace N
{
class A {};
void swap(const A &a, const A &b);
}

int main()
{
N::A a, b;
swap(a, b); // A::swap()
}

Since ADL is used as a "last resort",
the compiler will use another swap
function if it can be found (such as
with a using directive/declaration or
with a global swap function).

Be careful though: Microsoft Visual
C++ 7.0 does not handle ADL
correctly since it ignores it for
ordinary functions (as opposed to
operators). Therefore, the above
example does not compile. I do not know
for Visual C++ 7.1.
I thought I should have a using
declaration for std:swap before
the call. So that won't work as I
expected.

I don't understand that.

Maybe if you provided some actual
code we could help you more with
your problem than with theoritical
solutions.

Jonathan
 
F

Fraser Ross

"Jonathan Mcdougall"
You should have no problem if no
using directive is used:

# include <algorithm>

namespace N
{
class A {};
void swap(const A &a, const A &b);
}

int main()
{
N::A a, b;
swap(a, b); // A::swap()

Don't you mean N::swap()?

}

Since ADL is used as a "last resort",
the compiler will use another swap
function if it can be found (such as
with a using directive/declaration or
with a global swap function).

You said in the comment N::swap will be called. My compiler chooses
N::swap. It is the behaviour I want. I'd like to know where in the
standard is the rule for this.

In general ADL is not any kind of last resort. It leads to ambiguity.

Fraser.
 
F

Fraser Ross

"Fraser Ross"
"Jonathan Mcdougall"

Don't you mean N::swap()?



You said in the comment N::swap will be called. My compiler chooses
N::swap. It is the behaviour I want. I'd like to know where in the
standard is the rule for this.

N::swap is called because of the rule, prefer nontemplates. Incidentally
the constness is wrong with the parameters.

If N::swap is a template there is ambiguity. Probably I would write a
nontemplate N::swap specifically for parameters of A&. Using:
{
using namespace std;
swap(a1,a2);
}
is rather a lot of code so I am in favour of the STL container way of doing
swap now. That is put a partial specialisation of swap in namespace std
which calls a member function called swap of the class.

I wish I could remember where in Effective STL it says something about
whether a program is allowed to add to STL.

Fraser.
 
J

Jonathan Mcdougall

Yes I do.

3.4.2 in the 1996 working draft.

"When an unqualified name is used as the
postfix-expression in a function call (_expr.call_),
other namespaces not considered during the usual
unqualified look up (_basic.lookup.unqual_) may be
searched; this search depends on the types of the
arguments."

Umm... no. Without adl, this

# include <iostream>

int main()
{
std::cout << "hello";
}

would not work.
N::swap is called because of the rule, prefer
nontemplates.

In my example, no. It's because there is *no*
other swap function declared in this scope.
Incidentally the constness is wrong
with the parameters.

What? Passing a non-const to a const is quite
correct imo.
If N::swap is a template there is ambiguity.

With which one?
Probably I would write a nontemplate N::swap
specifically for parameters of A&. Using:

{
using namespace std;
swap(a1,a2);
}

is rather a lot of code so I am in favour of the
STL container way of doing swap now. That is put
a partial specialisation of swap in namespace std
which calls a member function called swap of the
class.

You may do that.
I wish I could remember where in Effective STL it
says something about whether a program is
allowed to add to STL.

17.3.3.1 in the 1996 draft.

"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
behaviour 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.20)"

By the way, try to post one message at a time.
 
F

Fraser Ross

"Jonathan Mcdougall"
3.4.2 in the 1996 working draft.

"When an unqualified name is used as the
postfix-expression in a function call (_expr.call_),
other namespaces not considered during the usual
unqualified look up (_basic.lookup.unqual_) may be
searched; this search depends on the types of the
arguments."

Thats not the reason. I have already given it in my later post: N::swap is
called because of the rule, prefer nontemplates. Actually I did not notice
that there is not a using directive but it would not matter.



Umm... no. Without adl, this

# include <iostream>

int main()
{
std::cout << "hello";
}

would not work.

I know its used there. You said that functions found with ADL are not
prefered to any found with a using directive but they result in ambiguity.
A global function is in the almost immediate scope so its prefered and a
function named with a using declaration is prefered over that.

Fraser.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top