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?
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
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
}
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
}