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