简体   繁体   中英

Overloading function doesn't work with complex

I have written this simple C++ code to swap any two variables. It works for int and double, but doesn't work for complex numbers, any idea why?

#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;
}

This is the error:

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>]

名称限制,更改为:: swap即可解决此问题。

The problem is that argument-dependent lookup is applied because you are calling a function template . If you had a plain function, there would be no ambiguity:

#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);
}

This is because of C++11 3.4.2:

Let X be the lookup set produced by unqualified lookup (3.4.1) and let Y be the lookup set produced by argument dependent lookup (defined as follows). If X contains

— a declaration of a class member, or

— a block-scope function declaration that is not a using-declaration, or

— a declaration that is neither a function or a function template

then Y is empty. Otherwise Y is the set of declarations found in the namespaces associated with the argument types as described below. The set of declarations found by the lookup of the name is the union of X and Y .

In the above case, X contains a block-scope function declaration.

However, if the unqualified lookup finds the function template you provided, then the ADL rules say that the argument-dependent lookup set is also considered. Since std::complex<double> lives in the std namespace, this namespace is also searched for the name swap , which already exists (by 20.2.2).

You can prevent argument-dependent lookup by wrapping the function name in parentheses:

(swap)(r, s);

This way, only the unqualified lookup is considered.

The compiler says it is confused because of two functions : yours and the standard std::swap. It consider std::swap too because std::complex is member of std::namespace, it's calling Argument Dependant Lookup. If you want to explicitly test your swap, you can use :: scope resolution operator, ie ::swap instead of swap. It will make another kind of lookup : Qualified Name Lookup solving the ambiguity.

Nonetheless, std::swap works well and do the job, except as exercise, include utility standard header, make a using std::swap, and it will work fine :

#include<utility>

//before needed (closest)
using std::swap;
swap(/*arguments*/);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM