函数模板重载 - 专用化

Function Template Overloading - Specialization

本文关键字:专用 重载 函数模板      更新时间:2023-10-16

根据C++编程语言,特别版,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: 注意:候选:std::complex<_Tp> std::sqrt(const std::complex<_Tp>&( [_Tp = double]

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

选项 #1

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

选项 #2

引用函数时使用限定名:

::sqrt(z);

选项 #3

通过使用括号禁用 ADL:

(sqrt)(z);