c++ - Operator overloading, name resolution and namespaces -
i light shed on puzzling situation involving adl, namespaces , operator overloading.
let foo library defines class ( deriv) in own namespace, along templated operator * returns class.
namespace foo { class deriv {}; class {}; template <typename t> operator* ( t x, const deriv& d ) { return another();} } now use foo's class in own library bar, defines operator *, time float.
namespace bar { typedef foo::deriv myderiv; myderiv operator* (float x, const myderiv& d) { return myderiv();} } i observe difference in compiler behaviour depending whether 1 inside namespace bar or not.
this function (bar::f1) compiles, using second version of operator * :
namespace bar { void f1() { bar::myderiv a; bar::myderiv b = 3.f * a; } } while same function outside namespace bar (f2()) fails compile, because compiler attempts use foo::operator* , cannot guess must use bar::operator*.
void f2() { bar::myderiv a; bar::myderiv b = 3.f * a; // error : cannot convert foo:another bar::myderiv } you can see code live here :http://ideone.com/pkpeoy
now, if foo::operator* not templated , defined foo::operator*(float, const deriv& d); both functions fail compile same error (ambiguous operator overload), can seen here : http://ideone.com/wi1ews
so, facing situation, puzzling me
in templated case, when compiling
f2, compiler considers usingfoo::operator*notbar::operator*, while in non-templated case, considers using both (and refuses go further because of ambiguity). what makes compiler behave differently ?a user of library bar outside
bar::namespace, yet wantbar::operator*used, , notfoo::operator*. considered explicitely callingbar::operator*(3.f,a), ugly, or inserting own operator in global namespace, reckon bad thing. is there option missing, or doing wrong ?
in templated case, when compiling
f2, compiler considers usingfoo::operator*notbar::operator*, while in non-templated case, considers using both (and refuses go further because of ambiguity). makes compiler behave differently ?
in both cases compiler considers using both, in case of templated operator*, call not ambiguous since there non-templated function parameter types matches arguments (try replace 3.f 3. , see templated version found). typically:
template <typename t> void g (t) { } void g (float) { } g(0.f); // ok, overload float preferred on templated version a user of library bar outside
bar::namespace, yet wantbar::operator*used, , not foo::operator*. considered explicitely callingbar::operator*(3.f,a), ugly, or inserting own operator in global namespace, reckon bad thing. there option missing, or doing wrong ?
unfortunately, adl not find overload since parameters of operator* float , myderiv defined inside namespace foo. 1 possible way inherit foo::deriv:
namespace bar { struct myderiv: public foo::deriv {}; myderiv operator* (float x, const myderiv& d) { return myderiv();} } another 1 declare overload operator* inside foo namespace:
namespace bar { typedef foo::deriv myderiv; } namespace foo { bar::myderiv operator* (float x, const bar::myderiv& d) { return bar::myderiv(); } }
Comments
Post a Comment