Re: Comeau and G++ disagree. Compiler bug?
 
Victor Bazarov wrote:
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.
Thanks,
The non-const reference and temporary was deliberately designed to catch
someone out after a previous question where it had been const and the
version of f in namespace A had been a function to illustrate Koenig
lookup. I wasn't 100% sure it would pick the function over the
constructor for f though.
Am I right in thinking non-const temporary reference binding will be
changing in C++0X? Or am I getting confused? I seem to recall reading
something about it a while back.
I'll be filing a bug against g++ shortly given that g++ (GCC) 4.3.0
20070720 also seems to have this problem.
Alan