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.