If I have a little bit of code like:
using namespace std;
namespace myNamespace
{
vector<float> sqrt( vector<float> v ) { return v; }
void func()
{
vector<float> myVec = { 1, 2, 3, 4 };
std::cout << sqrt( myVec )[0] << std::endl;
float myFloat = 4.0f;
std::cout << sqrt( myFloat ) << std::endl; // need to use std::sqrt()
}
}
then it won't compile unless I changed the marked line to use std::sqrt
. Why? I understand that if I tried to redefine sqrt(float)
in myNamespace
then I'd have to qualify with std::
if I wanted the standard library version to be used. The compiler appears to try to convert myFloat
rather than just use a function in another (std
) namespace.
One way I found to get around this is to define sqrt(vector<float>)
in the std
namespace but that doesn't quite feel right and answers to this question suggest overloading in std
is illegal. Probably not the way to go then...
How can I overload sqrt
(or any other standard library cmath function, for that matter) so that I don't have to always qualify which one to use and have the compiler select based on the passed function parameters?
Thanks.
The statement using namespace std is generally considered bad practice. The alternative to this statement is to specify the namespace to which the identifier belongs using the scope operator(::) each time we declare a type.
While this practice is okay for example code, pulling in the entire std namespace into the global namespace is not good as it defeats the purpose of namespaces and can lead to name collisions. This situation is called namespace pollution.
Namespaces in C++ You only need to prefix the function you wish to call with namespace_name:: -- similar to how you would call a static member function of a class. Another convenience of namespaces is that they allow you to use the same function name, when it makes sense to do so, to perform multiple different actions.
In C++, name lookup doesn't care about parameters type, only the name matters. When the compiler looks for a function named sqrt
, it will always find your version first (since the lookup starts with the enclosing namespace), and stops there.
You must help the compiler by bringing the name from std::
into scope with a using
directive in your namespace :
namespace myNamespace
{
using std::sqrt
...
}
Then, standard overload resolution will take place to distinguish between your sqrt
and std::sqrt
, and will select the correct sqrt
function to be called.
To avoid any ambiguity, you should always qualify the name (std::sqrt
or myNamespace::sqrt
)
Notes:
As pointed out by Simple, Argument Dependent Lookup (ADL) makes std::sqrt
available for name lookup in the first case (since vector
is in std::
), but it doesn't change the problem you're facing.
Declaring your own sqrt
function in std::
is a very bad idea (forbidden by the standard, except for template specializations)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With