0

我编写了这个简单的 C++ 代码来交换任何两个变量。它适用于 int 和 double,但不适用于复数,知道为什么吗?

#include <iostream>  
#include <complex>  

using std::cout; 
using std::endl; 
using std::complex; 

template <class T>

inline void swap(T& d, T& s)
{
    T temp = d;
    d = s;
    s = temp;
}


int main()
{
   int m=5, n=10;
   double x=5.3, y=10.6;
   complex<double> r(2.4, 3.5), s(3.4, 6.7);

   cout << "inputs:  " << m << " , " << n << endl;
   swap(m, n);
   cout << "outputs: " << m << " , " << n << endl;

   cout << "double inputs:  " << x << " , " << y << endl;
   swap(x, y);
   cout << "double outputs: " << x << " , " << y << endl;

   cout << "complex inputs:  " << r << " , " << s << endl;
   swap(r, s);
   cout << "complex outputs: " << r << " , " << s << endl;
}

这是错误:

g++ 02.swap.template.cpp -o c.out.02
02.swap.template.cpp: In function ‘int main()’:
02.swap.template.cpp:37:13: error: call of overloaded ‘swap(std::complex<double>&, std::complex<double>&)’ is ambiguous
02.swap.template.cpp:37:13: note: candidates are:
02.swap.template.cpp:13:13: note: void swap(T&, T&) [with T = std::complex<double>]
/usr/include/c++/4.6/bits/move.h:122:5: note: void std::swap(_Tp&, _Tp&) [with _Tp = std::complex<double>]
4

3 回答 3

3

名称冲突,更改为 ::swap 解决了这个问题。

于 2013-11-06T01:11:13.500 回答
2

问题是应用了依赖于参数的查找,因为您正在调用函数模板。如果你有一个简单的函数,就不会有歧义:

#include <complex>

void swap(complex<double> & d, complex<double> & s)
{
    complex<double> temp = d;
    d = s;
    s = temp;
}


int main()
{
   std::complex<double> r(2.4, 3.5), s(3.4, 6.7);
   swap(r, s);
}

这是因为 C++11 3.4.2:

X为由非限定查找 (3.4.1) 生成的查找集,让Y为由参数相关查找生成的查找集(定义如下)。如果X包含

— 类成员的声明,或

— 不是 using 声明的块范围函数声明,或

— 既不是函数也不是函数模板的声明

那么Y为空。否则Y是在与参数类型关联的命名空间中找到的一组声明,如下所述。通过名称查找找到的声明集是XY的并集。

在上面的例子中,X包含一个块范围的函数声明。

但是,如果非限定查找找到了您提供的函数模板,则 ADL 规则会说明还考虑参数相关查找集。由于std::complex<double>存在于std命名空间中,因此还会在此命名空间中搜索swap已经存在的 name (到 20.2.2 为止)。

您可以通过将函数名称括在括号中来防止依赖于参数的查找:

(swap)(r, s);

这样,只考虑不合格的查找。

于 2013-11-06T01:25:51.630 回答
0

编译器说它因为两个函数而感到困惑:你的和标准的 std::swap。它也考虑 std::swap 因为 std::complex 是 std::namespace 的成员,它正在调用 Argument Dependent Lookup。如果你想显式地测试你的swap,你可以使用:: 范围解析操作符,即::swap 而不是swap。它将进行另一种查找:Qualified Name Lookup 解决歧义。

尽管如此,std::swap 可以很好地完成工作,除了作为练习,包括实用程序标准头,使用 std::swap 时,它会正常工作:

#include<utility>

//before needed (closest)
using std::swap;
swap(/*arguments*/);
于 2013-11-06T01:14:16.317 回答