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