Make ext allocators support heterogeneous equality comparison

Message ID 20181011113242.GA18739@redhat.com
State New
Headers show
Series
  • Make ext allocators support heterogeneous equality comparison
Related show

Commit Message

Jonathan Wakely Oct. 11, 2018, 11:32 a.m.
The Allocator requirements include the ability to compare different
specializations of the same allocator class template. This did not work
for __gnu_cxx::new_allocator and other extension allocators.  This patch
replaces the equality operators for those allocators with inline friends
that support heterogeneous comparisons.  (I'm not changing all ext
allocators because some are bit-rotted already).

Additionally, the equality operators for comparing two std::allocator
objects of the same type are now defined as inline friends. Those
overloads don't need to be declared at namespace scope, because they
aren't specified in the standard (but they're needed in this
implementation to avoid ambiguities caused by the extra overloads
defined for the base allocator type).

	* include/bits/allocator.h
	(operator==(const allocator<_Tp>&, const allocator<_Tp>))
	(operator!=(const allocator<_Tp>&, const allocator<_Tp>)): Replace
	with inline friends.
	* include/ext/debug_allocator.h (operator==, operator!=): Replace
	with inline friend functions that compare to rebound allocators.
	* include/ext/malloc_allocator.h (operator==, operator!=): Likewise.
	* include/ext/new_allocator.h (operator==, operator!=): Likewise.
	* testsuite/ext/debug_allocator/eq.cc: New test.
	* testsuite/ext/ext_pointer/alloc_eq.cc: New test.
	* testsuite/ext/malloc_allocator/eq.cc: New test.
	* testsuite/ext/new_allocator/eq.cc: New test.


Tested x86_64-linux, committed to trunk.
commit 6928679848204dc6637a9d25f2c8e932e62285c6
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Oct 10 20:14:50 2018 +0100

    Make ext allocators support heterogeneous equality comparison
    
    The Allocator requirements include the ability to compare different
    specializations of the same allocator class template. This did not work
    for __gnu_cxx::new_allocator and other extension allocators.  This patch
    replaces the equality operators for those allocators with inline friends
    that support heterogeneous comparisons.  (I'm not changing all ext
    allocators because some are bit-rotted already).
    
    Additionally, the equality operators for comparing two std::allocator
    objects of the same type are now defined as inline friends. Those
    overloads don't need to be declared at namespace scope, because they
    aren't specified in the standard (but they're needed in this
    implementation to avoid ambiguities caused by the extra overloads
    defined for the base allocator type).
    
            * include/bits/allocator.h
            (operator==(const allocator<_Tp>&, const allocator<_Tp>))
            (operator!=(const allocator<_Tp>&, const allocator<_Tp>)): Replace
            with inline friends.
            * include/ext/debug_allocator.h (operator==, operator!=): Replace
            with inline friend functions that compare to rebound allocators.
            * include/ext/malloc_allocator.h (operator==, operator!=): Likewise.
            * include/ext/new_allocator.h (operator==, operator!=): Likewise.
            * testsuite/ext/debug_allocator/eq.cc: New test.
            * testsuite/ext/ext_pointer/alloc_eq.cc: New test.
            * testsuite/ext/malloc_allocator/eq.cc: New test.
            * testsuite/ext/new_allocator/eq.cc: New test.

Patch

diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index c4e3a4b9c15..d9d1d26e13a 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -148,6 +148,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       ~allocator() _GLIBCXX_NOTHROW { }
 
+      friend bool
+      operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW
+      { return true; }
+
+      friend bool
+      operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW
+      { return false; }
+
       // Inherit everything else.
     };
 
@@ -157,24 +165,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_NOTHROW
     { return true; }
 
-  template<typename _Tp>
-    inline bool
-    operator==(const allocator<_Tp>&, const allocator<_Tp>&)
-    _GLIBCXX_NOTHROW
-    { return true; }
-
   template<typename _T1, typename _T2>
     inline bool
     operator!=(const allocator<_T1>&, const allocator<_T2>&)
     _GLIBCXX_NOTHROW
     { return false; }
 
-  template<typename _Tp>
-    inline bool
-    operator!=(const allocator<_Tp>&, const allocator<_Tp>&)
-    _GLIBCXX_NOTHROW
-    { return false; }
-
   // Invalid allocator<cv T> partial specializations.
   // allocator_traits::rebind_alloc can be used to form a valid allocator type.
   template<typename _Tp>
diff --git a/libstdc++-v3/include/ext/debug_allocator.h b/libstdc++-v3/include/ext/debug_allocator.h
index dce224f05ed..3bc750e473b 100644
--- a/libstdc++-v3/include/ext/debug_allocator.h
+++ b/libstdc++-v3/include/ext/debug_allocator.h
@@ -174,16 +174,18 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       max_size() const throw()
       { return _Traits::max_size(_M_allocator) - _M_extra; }
 
-      friend bool
-      operator==(const debug_allocator& __lhs, const debug_allocator& __rhs)
-      { return __lhs._M_allocator == __rhs._M_allocator; }
-    };
+      template<typename _Alloc2>
+	friend bool
+	operator==(const debug_allocator& __lhs,
+		   const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
+	{ return __lhs._M_allocator == debug_allocator(__rhs)._M_allocator; }
 
-  template<typename _Alloc>
-    inline bool
-    operator!=(const debug_allocator<_Alloc>& __lhs,
-	       const debug_allocator<_Alloc>& __rhs)
-    { return !(__lhs == __rhs); }
+      template<typename _Alloc2>
+	friend bool
+	operator!=(const debug_allocator& __lhs,
+		   const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
+	{ return !(__lhs == __rhs); }
+    };
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/include/ext/malloc_allocator.h b/libstdc++-v3/include/ext/malloc_allocator.h
index 8eaf5d44cf7..1ae53b11ddb 100644
--- a/libstdc++-v3/include/ext/malloc_allocator.h
+++ b/libstdc++-v3/include/ext/malloc_allocator.h
@@ -166,17 +166,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       void 
       destroy(pointer __p) { __p->~_Tp(); }
 #endif
-    };
 
-  template<typename _Tp>
-    inline bool
-    operator==(const malloc_allocator<_Tp>&, const malloc_allocator<_Tp>&)
-    { return true; }
-  
-  template<typename _Tp>
-    inline bool
-    operator!=(const malloc_allocator<_Tp>&, const malloc_allocator<_Tp>&)
-    { return false; }
+      template<typename _Up>
+	friend bool
+	operator==(const malloc_allocator&, const malloc_allocator<_Up>&)
+	_GLIBCXX_NOTHROW
+	{ return true; }
+
+      template<typename _Up>
+	friend bool
+	operator!=(const malloc_allocator&, const malloc_allocator<_Up>&)
+	_GLIBCXX_NOTHROW
+	{ return false; }
+    };
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/include/ext/new_allocator.h b/libstdc++-v3/include/ext/new_allocator.h
index 7c50731736b..83c894ce0a7 100644
--- a/libstdc++-v3/include/ext/new_allocator.h
+++ b/libstdc++-v3/include/ext/new_allocator.h
@@ -157,18 +157,20 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       void
       destroy(pointer __p) { __p->~_Tp(); }
 #endif
+
+      template<typename _Up>
+	friend bool
+	operator==(const new_allocator&, const new_allocator<_Up>&)
+	_GLIBCXX_NOTHROW
+	{ return true; }
+
+      template<typename _Up>
+	friend bool
+	operator!=(const new_allocator&, const new_allocator<_Up>&)
+	_GLIBCXX_NOTHROW
+	{ return false; }
     };
 
-  template<typename _Tp>
-    inline bool
-    operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
-    { return true; }
-
-  template<typename _Tp>
-    inline bool
-    operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
-    { return false; }
-
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/testsuite/ext/debug_allocator/eq.cc b/libstdc++-v3/testsuite/ext/debug_allocator/eq.cc
new file mode 100644
index 00000000000..4623fde384e
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/debug_allocator/eq.cc
@@ -0,0 +1,31 @@ 
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+
+#include <ext/debug_allocator.h>
+
+__gnu_cxx::debug_allocator< std::allocator<int> > i;
+__gnu_cxx::debug_allocator< std::allocator<float> > f;
+
+bool b1 = i == i;
+bool b2 = f == f;
+bool b3 = i == f;
+
+bool n1 = i != i;
+bool n2 = f != f;
+bool n3 = i != f;
diff --git a/libstdc++-v3/testsuite/ext/ext_pointer/alloc_eq.cc b/libstdc++-v3/testsuite/ext/ext_pointer/alloc_eq.cc
new file mode 100644
index 00000000000..0b846cd6a1f
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/ext_pointer/alloc_eq.cc
@@ -0,0 +1,31 @@ 
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+
+#include <ext/extptr_allocator.h>
+
+__gnu_cxx::_ExtPtr_allocator<int> i;
+__gnu_cxx::_ExtPtr_allocator<float> f;
+
+bool b1 = i == i;
+bool b2 = f == f;
+bool b3 = i == f;
+
+bool n1 = i != i;
+bool n2 = f != f;
+bool n3 = i != f;
diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/eq.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/eq.cc
new file mode 100644
index 00000000000..12063f1f5eb
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/malloc_allocator/eq.cc
@@ -0,0 +1,31 @@ 
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+
+#include <ext/malloc_allocator.h>
+
+__gnu_cxx::malloc_allocator<int> i;
+__gnu_cxx::malloc_allocator<float> f;
+
+bool b1 = i == i;
+bool b2 = f == f;
+bool b3 = i == f;
+
+bool n1 = i != i;
+bool n2 = f != f;
+bool n3 = i != f;
diff --git a/libstdc++-v3/testsuite/ext/new_allocator/eq.cc b/libstdc++-v3/testsuite/ext/new_allocator/eq.cc
new file mode 100644
index 00000000000..6dc60038802
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/new_allocator/eq.cc
@@ -0,0 +1,31 @@ 
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+
+#include <ext/new_allocator.h>
+
+__gnu_cxx::new_allocator<int> i;
+__gnu_cxx::new_allocator<float> f;
+
+bool b1 = i == i;
+bool b2 = f == f;
+bool b3 = i == f;
+
+bool n1 = i != i;
+bool n2 = f != f;
+bool n3 = i != f;