Consider this very simple example, where I have template wrapper class for which are defined operators:
template <class T>
struct W {
W(const T&) {}
};
template <class T>
T operator + (const W<T>& w1, const W<T>& w2) { return T(); }
And this surprisingly cannot match for wrapped type, with simple error from gcc4.5.1 that cannot find operator + (A,A):
struct A {};
int main() {
A a1, a2;
A a3 = a1 + a2;
}
I’ve tried to find the reason by testing non template wrapper, but this version works:
struct A {};
struct WA {
WA(const A&) {}
};
A operator + (const WA& w1, const WA& w2) { return A(); }
int main() {
A a1, a2;
A a3 = a1 + a2;
}
What is the reason of such difference of arguments matching, and what to do to make template version works?
[UPDATE]
I took your answers into consideration, and I’ve changed the example to be a little opposite way, still with the same results – template version is complaining for missing operator +, while non template works fine. Now I have explicit cast operator to explicit wrapper class:
template version
template <class T>
struct W {
};
template <class T>
T operator + (const W<T>& w1, const W<T>& w2) { return T(); }
struct A {
operator W<A>() const { return W<A>(); }
};
not template
struct WA {
};
struct A {
operator WA() const { return WA(); }
};
A operator + (const WA& w1, const WA& w2) { return A(); }
I am trying to avoid this solution:
A a3 = W(a1) + W(a2);
No hope for this to work?
A a3 = a1 + a2;
Template argument deduction comes before overload resolution. But template argument deduction does not consider implicit conversions, so your templated operator is never even considered.
Implicit conversions are only applied after an overload has been chosen.
You can say
A a3 = W(a1) + W(a2);, though.