Alan Woodland wrote:
#include <iostream>
namespace A {
class Foo { };
struct f {
public:
f(const Foo& f) { std::cout << "ctor" << std::endl; }
};
}
template <typename T>
void f(const T& t) { std::cout << "Template ref" << std::endl; }
void f(A::Foo& f) { std::cout << "Plain ref" << std::endl; }
int main() {
f(A::Foo());
return 0;
}
G++ doesn't accept it and says:
test.cc: In function 'int main()':
test.cc:5: error: 'struct A::f' is not a function,
test.cc:14: error: conflict with 'void f(A::Foo&)'
test.cc:17: error: in call to 'f'
G++ version was:
g++ (GCC) 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
AFAICT, G++ is mistaken. It cannot be a construction of a temporary
of type 'f', types are not found using ADL for this syntax. In order
to look 'f' up using ADL, it has to be deemed a function call. By
the time ADL is employed, the syntax 'f(A::Foo())' cannot be
"explicit type conversion (functional notation)". It only can be
"type conversion" if 'f' is already deduced as a type, which it
cannot be since 'A::f' type is not visible.
That aside, it cannot be 'f(A::Foo&)' since the reference to a
non-const 'A::Foo' cannot be bound to a temporary ('A::Foo()'),
which leaves the only choice: the template. Now, if you change the
"plain ref" function to
void f(A::Foo const&);
then it will be chosen over the template since in rules of the
overload resolution a non-template function is always preferred over
a template instantiation.
Koenig lookup. I wasn't 100% sure it would pick the function over the
constructor for f though.