Commit c7790bdb by Jonathan Wakely Committed by Jonathan Wakely

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.

From-SVN: r265036
parent e7336b8e
2018-10-11 Jonathan Wakely <jwakely@redhat.com>
* 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.
2018-10-10 Jonathan Wakely <jwakely@redhat.com> 2018-10-10 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/87544 PR libstdc++/87544
......
...@@ -148,6 +148,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -148,6 +148,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~allocator() _GLIBCXX_NOTHROW { } ~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. // Inherit everything else.
}; };
...@@ -157,24 +165,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -157,24 +165,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NOTHROW _GLIBCXX_NOTHROW
{ return true; } { return true; }
template<typename _Tp>
inline bool
operator==(const allocator<_Tp>&, const allocator<_Tp>&)
_GLIBCXX_NOTHROW
{ return true; }
template<typename _T1, typename _T2> template<typename _T1, typename _T2>
inline bool inline bool
operator!=(const allocator<_T1>&, const allocator<_T2>&) operator!=(const allocator<_T1>&, const allocator<_T2>&)
_GLIBCXX_NOTHROW _GLIBCXX_NOTHROW
{ return false; } { return false; }
template<typename _Tp>
inline bool
operator!=(const allocator<_Tp>&, const allocator<_Tp>&)
_GLIBCXX_NOTHROW
{ return false; }
// Invalid allocator<cv T> partial specializations. // Invalid allocator<cv T> partial specializations.
// allocator_traits::rebind_alloc can be used to form a valid allocator type. // allocator_traits::rebind_alloc can be used to form a valid allocator type.
template<typename _Tp> template<typename _Tp>
......
...@@ -174,16 +174,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -174,16 +174,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
max_size() const throw() max_size() const throw()
{ return _Traits::max_size(_M_allocator) - _M_extra; } { return _Traits::max_size(_M_allocator) - _M_extra; }
template<typename _Alloc2>
friend bool friend bool
operator==(const debug_allocator& __lhs, const debug_allocator& __rhs) operator==(const debug_allocator& __lhs,
{ return __lhs._M_allocator == __rhs._M_allocator; } const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
}; { return __lhs._M_allocator == debug_allocator(__rhs)._M_allocator; }
template<typename _Alloc> template<typename _Alloc2>
inline bool friend bool
operator!=(const debug_allocator<_Alloc>& __lhs, operator!=(const debug_allocator& __lhs,
const debug_allocator<_Alloc>& __rhs) const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
{ return !(__lhs == __rhs); } { return !(__lhs == __rhs); }
};
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace } // namespace
......
...@@ -166,17 +166,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -166,17 +166,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void void
destroy(pointer __p) { __p->~_Tp(); } destroy(pointer __p) { __p->~_Tp(); }
#endif #endif
};
template<typename _Tp> template<typename _Up>
inline bool friend bool
operator==(const malloc_allocator<_Tp>&, const malloc_allocator<_Tp>&) operator==(const malloc_allocator&, const malloc_allocator<_Up>&)
_GLIBCXX_NOTHROW
{ return true; } { return true; }
template<typename _Tp> template<typename _Up>
inline bool friend bool
operator!=(const malloc_allocator<_Tp>&, const malloc_allocator<_Tp>&) operator!=(const malloc_allocator&, const malloc_allocator<_Up>&)
_GLIBCXX_NOTHROW
{ return false; } { return false; }
};
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace } // namespace
......
...@@ -157,17 +157,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -157,17 +157,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void void
destroy(pointer __p) { __p->~_Tp(); } destroy(pointer __p) { __p->~_Tp(); }
#endif #endif
};
template<typename _Tp> template<typename _Up>
inline bool friend bool
operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&) operator==(const new_allocator&, const new_allocator<_Up>&)
_GLIBCXX_NOTHROW
{ return true; } { return true; }
template<typename _Tp> template<typename _Up>
inline bool friend bool
operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&) operator!=(const new_allocator&, const new_allocator<_Up>&)
_GLIBCXX_NOTHROW
{ return false; } { return false; }
};
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace } // namespace
......
// 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;
// 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;
// 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;
// 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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment