当前位置:  开发笔记 > 编程语言 > 正文

为什么这个调用swap()模棱两可?

如何解决《为什么这个调用swap()模棱两可?》经验,为你挑选了2个好方法。

以下程序

#include 
#include 
#include 

namespace my_namespace
{


template
void swap(T& a, T& b)
{
  T tmp = std::move(a);
  a = std::move(b);
  b = std::move(tmp);
}

template>
class foo {};

}

int main()
{
  my_namespace::foo *a, *b;

  using my_namespace::swap;

  swap(a,b);

  return 0;
}

导致两者g++clang在我的系统上发出以下编译器错误:

$ clang -std=c++11 swap_repro.cpp -I.
swap_repro.cpp:28:3: error: call to 'swap' is ambiguous
  swap(a,b);
  ^~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/algorithmfwd.h:571:5: note: candidate function [with _Tp = my_namespace::foo > *]
    swap(_Tp&, _Tp&)
    ^
swap_repro.cpp:10:6: note: candidate function [with T = my_namespace::foo > *]
void swap(T& a, T& b)
     ^
1 error generated.

$ g++ -std=c++11 swap_repro.cpp -I.
swap_repro.cpp: In function ‘int main()’:
swap_repro.cpp:28:11: error: call of overloaded ‘swap(my_namespace::foo*&, my_namespace::foo*&)’ is ambiguous
   swap(a,b);
           ^
swap_repro.cpp:28:11: note: candidates are:
swap_repro.cpp:10:6: note: void my_namespace::swap(T&, T&) [with T = my_namespace::foo*]
 void swap(T& a, T& b)
      ^
In file included from /usr/include/c++/4.9/bits/stl_pair.h:59:0,
                 from /usr/include/c++/4.9/utility:70,
                 from /usr/include/c++/4.9/algorithm:60,
                 from swap_repro.cpp:1:
/usr/include/c++/4.9/bits/move.h:166:5: note: void std::swap(_Tp&, _Tp&) [with _Tp = my_namespace::foo*]
     swap(_Tp& __a, _Tp& __b)
     ^

我不明白为什么std::swap被认为是候选人超载,但它与foo使用它有关std::allocator.

消除foo第二个模板参数允许程序编译而不会出错.



1> T.C...:

因为std::allocator用作模板类型参数,所以std命名空间是ADL的关联命名空间.

[basic.lookup.argdep]/2,bullet 2,强调我的:

此外,如果T是类模板特化,则其关联的名称空间和类还包括:与模板类型参数(模板模板参数除外)提供的模板参数类型相关联的名称空间和类 ; 任何模板模板参数都是成员的名称空间; 以及用作模板模板参数的任何成员模板的类都是成员.

...和指针具有与它们指向的类型相同的关联命名空间/类集:

如果T是指向U或数组的指针U,则其关联的名称空间和类是与之关联的名称空间和类U.



2> Dietmar Kühl..:

基于参数类型可见的各种类型确定关联命名空间的集合.值得注意的是,对于类模板,关联的命名空间包括所有模板参数的关联命名空间.当使用依赖于参数的查找查找非限定函数时,将搜索所有关联的命名空间.

模板参数列表foo实际上是foo>,因此将命名空间std拖入图片中,并且已经存在swap()可用的一般过载.

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有