功能模板重载 - 专业化

nee*_*eKo 5 c++

根据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)
}   
Run Code Online (Sandbox Code Playgroud)

他说,尽管两个模板都是有效的候选者,但第二个模板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>);
                          ^
Run Code Online (Sandbox Code Playgroud)

我做错了什么(虽然我复制了角色的代码字符)?或者它是我的编译器的实现错误?

Pio*_*cki 2

完整的错误消息揭示了另外一个候选者:

/usr/local/include/c++/5.3.0/complex:894:5:注意:候选者:std::complex<_Tp> std::sqrt(const std::complex<_Tp>&) [with _Tp = double ]

即,存在于命名空间中的那个std,即 的std::sqrt重载std::complex由于您使用的是非限定名称,因此查找规则将扩展为在函数调用参数 ( ADL )的命名空间中搜索函数。解决办法如下:

选项1

更改函数的名称sqrt,以便它不会与标准库中的任何函数发生冲突。

选项#2

引用函数时使用限定名称:

::sqrt(z);
Run Code Online (Sandbox Code Playgroud)

选项#3

通过使用括号禁用 ADL:

(sqrt)(z);
Run Code Online (Sandbox Code Playgroud)