According to The C++ Programming Language, Special Edition, Bjarne Stroustrup, section 13.3.2:
template<class T> T sqrt(T);
template<class T> complex<T> sqrt(complex<T>);
void f(complex<double> z)
{
sqrt(z); // sqrt<double>(complex<double)
}
He states, that although both templates are valid candidates, the second one, sqrt<double>(complex<double>)
will be preferred over the first one, because it is the most specialized template.
My esteemed compiler, gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
seems to disagree:
ft.cpp: In function ‘void f(std::complex<double>)’:
ft.cpp:28:11: error: call of overloaded ‘sqrt(std::complex<double>&)’ is ambiguous
sqrt(z);
^
ft.cpp:28:11: note: candidates are:
ft.cpp:9:21: note: T sqrt(T) [with T = std::complex<double>]
template<class T> T sqrt(T);
^
ft.cpp:10:30: note: std::complex<_Tp> sqrt(std::complex<_Tp>) [with T = double]
template<class T> complex<T> sqrt(complex<T>);
^
Am I doing something wrong (although I copied the code character for character)? Or is it an implementation error for my compiler?
The complete error message reveals one more candidate:
/usr/local/include/c++/5.3.0/complex:894:5: note: candidate: std::complex<_Tp> std::sqrt(const std::complex<_Tp>&) [with _Tp = double]
i.e., the one that lives in the std
namespace, namely the std::sqrt
overload for std::complex
. Since you're using an unqualified name, the lookup rules are extended to search the function in the namespaces of function call arguments (ADL). The solutions are as follows:
Change the name of your sqrt
function so that it does not collide with any from the standard library.
Use a qualified name when referring to your function:
::sqrt(z);
Disable ADL by means of using parenthesis:
(sqrt)(z);
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