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:
<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?
This is due to ADL. Basically, here the namespace
app::halwill be automatically searched and so there are twosetMotor(one due to ADL and other because you explicitly specifiedusing app::control::setMotor) and hence the ambiguity.Method 1
You can disable(workaround) ADL by adding parenthesis around
setMotorwhen calling the function as shown below:Working demo
Method 2
Or you can be explicit about the call as shown below: