Given the following code:
#include <iostream>
struct Alice
{
template <typename A>
void operator|(const A& /*a*/) const
{
std::cout << "operator| member" << std::endl;
}
};
template <typename A>
void operator|(const A& /*a*/, const Alice& /*alice*/)
{
std::cout << "operator| non-member" << std::endl;
}
int main()
{
Alice a;
Alice b;
a | b;
return 0;
}
It compiles without warning with both GCC 4.8.1, 4.9 and clang 3.4, but gives different results.
$ g++ -Wall -Wextra -std=c++11 alice.cpp && ./a.out
operator| non-member
$ clang++ -Wall -Wextra -std=c++11 alice.cpp && ./a.out
operator| member
What causes this difference? How can I force the same behaviour?
EDIT: Interesting fact: removing the const
qualifier from the member function makes gcc prefer the member function also. It does not solve the problem, however.
EDIT: clang++ prefers the non-member instead, if -std=c++11
is not specified.
EDIT: ICC 14.0 prefers non-member, no warning emitted.
According to overload resolution, there are two viable functions: The specialization of the global operator|
-template with deduced arguments and the specialization of the member operator function template. Both have the same signature - the member function template has an implicit object parameter of type Alice const&
(see §13.3.1/4).
So both viable functions (after template argument deduction) have the same signature. And neither of the templates from which they were instantiated is more specialized than the other. So this is indeed an ambiguity and therefore ill-formed. Surprisingly, VC++ is correct.
How can I force the same behaviour?
Perhaps you should just remove the ambiguity, Clang, VC++ and GCC should have the same behavior then.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With