c++ - 为什么这个对 swap() 的调用模棱两可?

标签 c++ namespaces argument-dependent-lookup name-lookup class-template

下面的程序

#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在我的系统上发出以下编译器错误:

$ 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被认为是候选重载,但它与 foo 有关对 std::allocator<T> 的使用.

消除 foo的第二个模板参数允许程序编译没有错误。

最佳答案

因为std::allocator<T>用作模板类型参数,std namespace 是 ADL 的关联命名空间。

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

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.

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

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

关于c++ - 为什么这个对 swap() 的调用模棱两可?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34075718/

相关文章:

C++普通查找与参数相关查找

c++ - std::(customization point) 是否调用最合适的重载?

C++ - 类没有命名类型

c++ - 这种使用 std::string 的方式安全吗?

clojure - 为什么Clojure中的 "use"会调用 "in-ns"返回原来的命名空间?

c# - 关于构建领域驱动设计命名空间的一些问题

android - 在 Android 中导入 javax.namespace

c++ - boost 多精度 cpp_int 乘以 float

C++ Boost 任何尝试

c++ - 关于友元函数定义和命名空间范围