为什么对swap()的调用不明确? [英] Why is this call to swap() ambiguous?

查看:331
本文介绍了为什么对swap()的调用不明确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下程序

#include <algorithm>
#include <utility>
#include <memory>

namespace my_namespace
{


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

template<class T, class Alloc = std::allocator<T>>
class foo {};

}

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

  using my_namespace::swap;

  swap(a,b);

  return 0;
}

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

causes both g++ and clang to issue the following compiler error on my system:

$ 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<int, std::allocator<int> > *]
    swap(_Tp&, _Tp&)
    ^
swap_repro.cpp:10:6: note: candidate function [with T = my_namespace::foo<int, std::allocator<int> > *]
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<int>*&, my_namespace::foo<int>*&)’ 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<int>*]
 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<int>*]
     swap(_Tp& __a, _Tp& __b)
     ^

我不明白为什么std::swap被认为是候选超载,但这与foostd::allocator<T>的使用有关.

I don't understand why std::swap is being considered as a candidate overload, but it has something to do with foo's use of std::allocator<T>.

消除了foo的第二个模板参数,程序可以无错误地进行编译.

Eliminating foo's second template parameter allows the program to compile without error.

推荐答案

由于std::allocator<T>用作模板类型参数,因此std命名空间是ADL的关联命名空间.

Because std::allocator<T> is used as a template type argument, the std namespace is an associated namespace for ADL.

[basic.lookup.argdep]/2 ,项目2,重点是:

[basic.lookup.argdep]/2, bullet 2, emphasis mine:

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

Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template arguments are members.

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

...and pointers have the same set of associated namespaces/classes as the type they point to:

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

If T is a pointer to U or an array of U, its associated namespaces and classes are those associated with U.

这篇关于为什么对swap()的调用不明确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆