[copy-paste from email since I don't think Alisdair has gotten around to submitting the bug]
I'm currently working at home with GCC 4.4.1 (MinGW build) and as you might guess from the example, playing around with my own std lib implementation. I'm currently failing to get my swap overload for arrays to use ADL, and I'm running out of ideas. Want to run it past you in case I am pounding my head against a GCC bug. Note that the non-array version picks up ADL correctly, as can be seen by commenting out the line that chains the array-bases tests. I'm leaning towards this being an ADL implementation bug, but I'm still not 100% confident in my understanding of the rules in this area so wanted to run it past an expert before filing a bug report (which would be essentially the same code cleaned up and without the 'pass' tests as noise) If there is some subtle trick I am missing to enable ADL in this case, then I fear our language is already far too subtle to live... AlisdairM main.cpp #include <cstddef> #include <cstdio> #include <type_traits> using std::size_t; // DECLARE ALGORITHMS //=================== namespace std0x { template <typename T> auto move(T&&) -> typename std::remove_reference<T>::type &&; // 20.3.2, swap: template<typename T> void swap(T& a, T& b); template <typename T, size_t N> void swap(T (&a)[N], T (&b)[N]); } // DEFINE ALGORITHMS //=================== template <class T> auto std0x::move(T && value) -> typename std ::remove_reference<T>::type && { return static_cast<T &&>( value ); } // 20.3.2, swap: template<typename T> void std0x::swap(T& a, T& b) { auto tmp( move(a) ); a = move(b); b = move(tmp); } // Attempted workaround, guarantee namespace std0x on equal footing to ADL namespace impl { template <typename T, size_t N> void swap(T (&a)[N], T (&b)[N]) { for( size_t i = 0; i != N; ++i ) { using namespace std0x; // using std0x::swap; swap(a[i], b[i]); // Why will this not trigger ADL? GCC bug or me? } } } template <typename T, size_t N> void std0x::swap(T (&a)[N], T (&b)[N]) { impl::swap(a, b); // attempt to trigger ADL // for( size_t i = 0; i != N; ++i ) { //// using std0x::swap; // swap(a[i], b[i]);// Why will this not trigger ADL? GCC bug or me? // } } // TEST HARNESS //============= template<typename T> auto test_array() -> bool { using std::printf; using std0x::swap; T const init_a[3]{1,2,3}; T const init_b[3]{4,5,6}; // initialize again from rvalues, rather than risk copy ctor T a[3]{1,2,3}; T b[3]{4,5,6}; swap(a, b); for(unsigned i = 0; i != 3; ++i ) { if( a[i] != init_b[i]) { printf("Error, bad 'a' element\n"); return false; } if( b[i] != init_a[i]) { printf("Error, bad 'b' element\n"); return false; } } return true; } template<typename T> auto test() -> bool { using std::printf; using std0x::swap; T const init_a{13}; T const init_b{42}; // initialize again from rvalues, rather than risk copy ctor T a{13}; T b{42}; swap(a, b); if( a != init_b) { printf("Error, bad 'a'\n"); return false; } if( b != init_a) { printf("Error, bad 'b'\n"); return false; } return test_array<T>(); // return true; } // TEST DRIVER TYPES // ================= struct simple { int data; }; auto operator==(simple const & a, simple const & b ) -> bool { return a.data == b.data; } auto operator!=(simple const & a, simple const & b ) -> bool { return a.data != b.data; } struct move_only { int data; move_only(int a) : data{a} {} move_only(move_only const &) = delete; auto operator=(move_only const &) -> move_only & = delete; move_only(move_only && rhs) : data{rhs.data} { rhs.data = 0; } auto operator=(move_only && rhs) -> move_only & { data = rhs.data; rhs.data = 0; return *this; } }; auto operator==(move_only const & a, move_only const & b ) -> bool { return a.data == b.data; } auto operator!=(move_only const & a, move_only const & b ) -> bool { return a.data != b.data; } namespace barrier { struct adl_only { int data; adl_only(int a) : data{a} {} adl_only(adl_only const &) = delete; auto operator=(adl_only const &) -> move_only & = delete; }; void swap(adl_only & a, adl_only & b) { using std0x::swap; swap(a.data, b.data); } auto operator==(adl_only const & a, adl_only const & b ) -> bool { return a.data == b.data; } auto operator!=(adl_only const & a, adl_only const & b ) -> bool { return a.data != b.data; } } // TEST DRIVER // =========== int main() { printf( "Hello world!\n" ); int fails = 0; if( !test<int>() ) ++fails; if( !test<simple>() ) ++fails; if( !test<move_only>() ) ++fails; if( !test<barrier::adl_only>() ) ++fails; return fails; } -- Summary: Possible ADL bug in GCC 4.4.1 Product: gcc Version: 4.4.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jason at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43144