根据 The C++ Programming Language, Special Edition,Bjarne Stroustrup,第 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)
}
他说,虽然两个模板都是有效的候选者,但第二个模板,sqrt<double>(complex<double>)
将优先于第一个,因为它是最专业的模板。
我尊敬的编译器,gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
似乎不同意:
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>);
^
我是不是做错了什么(虽然我复制了字符代码字符)?还是我的编译器的实现错误?
最佳答案
完整的错误信息揭示了一个候选者:
/usr/local/include/c++/5.3.0/complex:894:5: note: candidate: std::complex<_Tp> std::sqrt(const std::complex<_Tp>&) [with _Tp = double]
即位于 std
命名空间中的那个,即 std::sqrt
std::complex
的重载。由于您使用的是非限定名称,因此扩展了查找规则以在函数调用参数 ( ADL) 的命名空间中搜索函数。解决方法如下:
选项#1
更改 sqrt
函数的名称,使其不会与标准库中的任何函数冲突。
选项#2
在引用您的函数时使用限定名称:
::sqrt(z);
选项 #3
通过使用括号来禁用 ADL:
(sqrt)(z);
关于c++ - 函数模板重载 - 特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35379422/