public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/43144]  New: Possible ADL bug in GCC 4.4.1
@ 2010-02-22 20:06 jason at gcc dot gnu dot org
  0 siblings, 0 replies; only message in thread
From: jason at gcc dot gnu dot org @ 2010-02-22 20:06 UTC (permalink / raw)
  To: gcc-bugs

[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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-02-22 20:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-22 20:06 [Bug c++/43144] New: Possible ADL bug in GCC 4.4.1 jason at gcc dot gnu dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).