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