For this function call expression
f(b);
the compiler finds the name f
declared in the global namespace. On the other hand, using the argument dependent lookup the compiler also looks through the namespace A
where the class B
is declared and also finds a function with the name f
. Neither function is the best candidate to be called. So there is an ambiguity.
Apart from using qualified names of the functions to avoid the ambiguity you could suppress the argument dependent lookup the following way
( f )( b );
The argument dependent lookup is very useful for searching friend functions that otherwise are not visible if they are only defined in a class that grants the friendship.
Here is a demonstrative program
#include <iostream>
namespace N
{
class A
{
private:
int x;
public:
A( int x ) : x( x ) {}
friend std::ostream & operator <<( std::ostream &os, const A &a )
{
return os << a.x;
}
};
}
int main()
{
N::A a( 10 );
std::cout << a << '\n';
return 0;
}
The program output is
10
If the argument dependent lookup did not exist then the friend operator <<
could not be called because it will not be found even in the namespace N
Consider the following program.
#include <iostream>
namespace N
{
class A
{
private:
int x;
public:
A( int x ) : x( x ) {}
friend void f( int x )
{
A a( x );
std::cout << a.x << '\n';
}
};
}
int main()
{
N::f( 10 );
return 0;
}
The friend function f
can not be called even if to specify the qualified name N::f
. For this program the compiler will issue an error saying that ‘f’ is not a member of ‘N’
. To make the function visible you need to declare it also outside the class A as for example
#include <iostream>
namespace N
{
class A
{
private:
int x;
public:
A( int x ) : x( x ) {}
friend void f( int x )
{
A a( x );
std::cout << a.x << '\n';
}
};
void f( int ); // make the function visible
}
int main()
{
N::f( 10 );
return 0;
}