The following program
#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; }
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) ^
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>
.
Eliminating foo
's second template parameter allows the program to compile without error.
Because std::allocator<T>
is used as a template type argument, the std
namespace is an associated namespace for ADL.
[basic.lookup.argdep]/2, bullet 2, emphasis mine:
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:
If
T
is a pointer toU
or an array ofU
, its associated namespaces and classes are those associated withU
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With