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 using foo::operator* not bar::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 want bar::operator* used, , not foo::operator*. considered explicitely calling bar::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 using foo::operator* not bar::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 want bar::operator* used, , not foo::operator*. considered explicitely calling bar::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

Popular posts from this blog

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12:test (default-test) on project.Error occurred in starting fork -

windows - Debug iNetMgr.exe unhandle exception System.Management.Automation.CmdletInvocationException -

configurationsection - activeMq-5.13.3 setup configurations for wildfly 10.0.0 -