c++ - 函数模板重载 - 特化

标签 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)
}   

他说,虽然两个模板都是有效的候选者,但第二个模板,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/

相关文章:

c++ - 我的函数总是返回一个巨大的数字

Xcode 中的 C++ 链接器错误

c++ - С++ 中的字符串文字是在静态内存中创建的吗?

c++ - 初始化后更改变量引用

c++ - CMake 链接顺序和 LINK_INTERFACE_MULTIPLICITY

c++ - 从新手角度解构一个C++代码块

c++ - 默认参数的静态绑定(bind)

c++ - 对 wstrings vector 进行排序,但不区分大小写

c++ - C++ 中 typedef 的前向声明

C++ 优化器删除具有副作用的对象