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.
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 ausing
directive in your namespace :Then, standard overload resolution will take place to distinguish between your
sqrt
andstd::sqrt
, and will select the correctsqrt
function to be called.To avoid any ambiguity, you should always qualify the name (
std::sqrt
ormyNamespace::sqrt
)Notes:
As pointed out by Simple, Argument Dependent Lookup (ADL) makes
std::sqrt
available for name lookup in the first case (sincevector
is instd::
), but it doesn't change the problem you're facing.Declaring your own
sqrt
function instd::
is a very bad idea (forbidden by the standard, except for template specializations)