Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Ambiguity while working with namespaces: Can `using` single thing leak anything else?

I have problem with ambiguity while working with namespaces.

Code:

namespace app::hal {
    enum class Motor {
        Left  = 0,
        Right = 1
    };

    void setMotor(Motor which, float duty);
}

namespace app::control {
    using Motor = app::hal::Motor;

    void setMotor(Motor which, float duty);
    float getMotor(Motor which);

}

inline void test() {
    using app::control::setMotor;
    using app::control::Motor;
    setMotor(Motor::Left, 0);
}

Error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<source>:24:17: error: call of overloaded 'setMotor(app::hal::Motor, int)' is ambiguous
   24 |         setMotor(Motor::Left, 0);
      |         ~~~~~~~~^~~~~~~~~~~~~~~~
<source>:15:14: note: candidate: 'void app::control::setMotor(Motor, float)'
   15 |         void setMotor(Motor which, float duty);
      |              ^~~~~~~~
<source>:8:14: note: candidate: 'void app::hal::setMotor(Motor, float)'
    8 |         void setMotor(Motor which, float duty);
      |              ^~~~~~~~

Godbolt link: https://godbolt.org/z/sqr4qKbd8

What is going on here? Why is setMotor call finding app::hal::setMotor as possibility when I didn’t using namespace app::hal nor using app::hal::setMotor? Isn’t this "leaking" namespace?

I don’t want to change app::hal contents, and I wanted so have same naming scheme for app::control. How can I make it work?

>Solution :

What is going on here?

This is due to ADL. Basically, here the namespace app::hal will be automatically searched and so there are two setMotor(one due to ADL and other because you explicitly specified using app::control::setMotor) and hence the ambiguity.


How can I make it work? I don’t want to change app::hal contents

Method 1

You can disable(workaround) ADL by adding parenthesis around setMotor when calling the function as shown below:

inline void test() {
    using app::control::setMotor;
    using app::control::Motor;
//--v--------v---------------------->adding parenthesis make this work because NO MORE ADL with parenthesis
    (setMotor)(Motor::Left, 0);   //works now with parenthesis 
}

Working demo


Method 2

Or you can be explicit about the call as shown below:

inline void test() {
    namespace appcon = app::control;
    appcon::setMotor(appcon::Motor::Left, 0); //works now
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading