Commit 437f43cc by Jonathan Wakely Committed by Jonathan Wakely

PR67085 pass comparison functions by reference in heap algorithms

	PR libstdc++/67085
	* include/bits/predefined_ops.h (_Iter_less_val, _Val_less_iter): Add
	converting constructors from _Iter_less_iter.
	(_Iter_comp_val, _Val_comp_iter): Add converting constructors from
	_Iter_comp_iter.
	(__iter_comp_val(_Iter_comp_iter<C>): Use converting constructor.
	(__val_comp_iter(_Iter_comp_iter<C>): Likewise.
	* include/bits/stl_heap.h (__is_heap_until, __push_heap, __pop_heap)
	(__make_heap, __sort_heap): Change _Compare parameters to references.
	(__is_heap, push_heap, __adjust_heap, __pop_heap, pop_heap)
	(__make_heap, make_heap, sort_heap, is_heap_until): Pass comparison
	functions as lvalues.
	(is_heap): Call __is_heap_until directly to avoid copying __comp.
	* testsuite/23_containers/priority_queue/67085.cc: Adjust test to
	count copies during construction with empty sequence.

From-SVN: r244656
parent d445d739
2017-01-19 Jonathan Wakely <jwakely@redhat.com> 2017-01-19 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/67085 PR libstdc++/67085
* include/bits/predefined_ops.h (_Iter_less_val, _Val_less_iter): Add
converting constructors from _Iter_less_iter.
(_Iter_comp_val, _Val_comp_iter): Add converting constructors from
_Iter_comp_iter.
(__iter_comp_val(_Iter_comp_iter<C>): Use converting constructor.
(__val_comp_iter(_Iter_comp_iter<C>): Likewise.
* include/bits/stl_heap.h (__is_heap_until, __push_heap, __pop_heap)
(__make_heap, __sort_heap): Change _Compare parameters to references.
(__is_heap, push_heap, __adjust_heap, __pop_heap, pop_heap)
(__make_heap, make_heap, sort_heap, is_heap_until): Pass comparison
functions as lvalues.
(is_heap): Call __is_heap_until directly to avoid copying __comp.
* testsuite/23_containers/priority_queue/67085.cc: Adjust test to
count copies during construction with empty sequence.
PR libstdc++/67085
* include/bits/stl_heap.h (__is_heap): Use _GLIBCXX_MOVE. * include/bits/stl_heap.h (__is_heap): Use _GLIBCXX_MOVE.
(__make_heap, __sort_heap): Don't use _GLIBCXX_MOVE inside loops. (__make_heap, __sort_heap): Don't use _GLIBCXX_MOVE inside loops.
* testsuite/23_containers/priority_queue/67085.cc: Adjust expected * testsuite/23_containers/priority_queue/67085.cc: Adjust expected
......
...@@ -50,6 +50,15 @@ namespace __ops ...@@ -50,6 +50,15 @@ namespace __ops
struct _Iter_less_val struct _Iter_less_val
{ {
#if __cplusplus >= 201103L
constexpr _Iter_less_val() = default;
#else
_Iter_less_val() { }
#endif
explicit
_Iter_less_val(_Iter_less_iter) { }
template<typename _Iterator, typename _Value> template<typename _Iterator, typename _Value>
bool bool
operator()(_Iterator __it, _Value& __val) const operator()(_Iterator __it, _Value& __val) const
...@@ -66,6 +75,15 @@ namespace __ops ...@@ -66,6 +75,15 @@ namespace __ops
struct _Val_less_iter struct _Val_less_iter
{ {
#if __cplusplus >= 201103L
constexpr _Val_less_iter() = default;
#else
_Val_less_iter() { }
#endif
explicit
_Val_less_iter(_Iter_less_iter) { }
template<typename _Value, typename _Iterator> template<typename _Value, typename _Iterator>
bool bool
operator()(_Value& __val, _Iterator __it) const operator()(_Value& __val, _Iterator __it) const
...@@ -141,6 +159,18 @@ namespace __ops ...@@ -141,6 +159,18 @@ namespace __ops
: _M_comp(_GLIBCXX_MOVE(__comp)) : _M_comp(_GLIBCXX_MOVE(__comp))
{ } { }
explicit
_Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
: _M_comp(__comp._M_comp)
{ }
#if __cplusplus >= 201103L
explicit
_Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
: _M_comp(std::move(__comp._M_comp))
{ }
#endif
template<typename _Iterator, typename _Value> template<typename _Iterator, typename _Value>
bool bool
operator()(_Iterator __it, _Value& __val) operator()(_Iterator __it, _Value& __val)
...@@ -155,7 +185,7 @@ namespace __ops ...@@ -155,7 +185,7 @@ namespace __ops
template<typename _Compare> template<typename _Compare>
inline _Iter_comp_val<_Compare> inline _Iter_comp_val<_Compare>
__iter_comp_val(_Iter_comp_iter<_Compare> __comp) __iter_comp_val(_Iter_comp_iter<_Compare> __comp)
{ return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp._M_comp)); } { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
template<typename _Compare> template<typename _Compare>
struct _Val_comp_iter struct _Val_comp_iter
...@@ -167,6 +197,18 @@ namespace __ops ...@@ -167,6 +197,18 @@ namespace __ops
: _M_comp(_GLIBCXX_MOVE(__comp)) : _M_comp(_GLIBCXX_MOVE(__comp))
{ } { }
explicit
_Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp)
: _M_comp(__comp._M_comp)
{ }
#if __cplusplus >= 201103L
explicit
_Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp)
: _M_comp(std::move(__comp._M_comp))
{ }
#endif
template<typename _Value, typename _Iterator> template<typename _Value, typename _Iterator>
bool bool
operator()(_Value& __val, _Iterator __it) operator()(_Value& __val, _Iterator __it)
...@@ -181,7 +223,7 @@ namespace __ops ...@@ -181,7 +223,7 @@ namespace __ops
template<typename _Compare> template<typename _Compare>
inline _Val_comp_iter<_Compare> inline _Val_comp_iter<_Compare>
__val_comp_iter(_Iter_comp_iter<_Compare> __comp) __val_comp_iter(_Iter_comp_iter<_Compare> __comp)
{ return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp._M_comp)); } { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
template<typename _Value> template<typename _Value>
struct _Iter_equals_val struct _Iter_equals_val
......
...@@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Compare> typename _Compare>
_Distance _Distance
__is_heap_until(_RandomAccessIterator __first, _Distance __n, __is_heap_until(_RandomAccessIterator __first, _Distance __n,
_Compare __comp) _Compare& __comp)
{ {
_Distance __parent = 0; _Distance __parent = 0;
for (_Distance __child = 1; __child < __n; ++__child) for (_Distance __child = 1; __child < __n; ++__child)
...@@ -91,8 +91,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -91,8 +91,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline bool inline bool
__is_heap(_RandomAccessIterator __first, _Distance __n) __is_heap(_RandomAccessIterator __first, _Distance __n)
{ {
return std::__is_heap_until(__first, __n, __gnu_cxx::__ops::_Iter_less_iter __comp;
__gnu_cxx::__ops::__iter_less_iter()) == __n; return std::__is_heap_until(__first, __n, __comp) == __n;
} }
template<typename _RandomAccessIterator, typename _Compare, template<typename _RandomAccessIterator, typename _Compare,
...@@ -100,8 +100,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -100,8 +100,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline bool inline bool
__is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n) __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
{ {
return std::__is_heap_until(__first, __n, __gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp));
__gnu_cxx::__ops::__iter_comp_iter(__comp)) == __n; return std::__is_heap_until(__first, __n, __cmp) == __n;
} }
template<typename _RandomAccessIterator> template<typename _RandomAccessIterator>
...@@ -126,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -126,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void void
__push_heap(_RandomAccessIterator __first, __push_heap(_RandomAccessIterator __first,
_Distance __holeIndex, _Distance __topIndex, _Tp __value, _Distance __holeIndex, _Distance __topIndex, _Tp __value,
_Compare __comp) _Compare& __comp)
{ {
_Distance __parent = (__holeIndex - 1) / 2; _Distance __parent = (__holeIndex - 1) / 2;
while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
...@@ -165,10 +165,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -165,10 +165,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_irreflexive(__first, __last);
__glibcxx_requires_heap(__first, __last - 1); __glibcxx_requires_heap(__first, __last - 1);
__gnu_cxx::__ops::_Iter_less_val __comp;
_ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
std::__push_heap(__first, _DistanceType((__last - __first) - 1), std::__push_heap(__first, _DistanceType((__last - __first) - 1),
_DistanceType(0), _GLIBCXX_MOVE(__value), _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
__gnu_cxx::__ops::__iter_less_val());
} }
/** /**
...@@ -200,11 +200,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -200,11 +200,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
__glibcxx_requires_heap_pred(__first, __last - 1, __comp); __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
__decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
__cmp(_GLIBCXX_MOVE(__comp));
_ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
std::__push_heap(__first, _DistanceType((__last - __first) - 1), std::__push_heap(__first, _DistanceType((__last - __first) - 1),
_DistanceType(0), _GLIBCXX_MOVE(__value), _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
__gnu_cxx::__ops::
__iter_comp_val(_GLIBCXX_MOVE(__comp)));
} }
template<typename _RandomAccessIterator, typename _Distance, template<typename _RandomAccessIterator, typename _Distance,
...@@ -231,16 +231,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -231,16 +231,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ (__secondChild - 1))); + (__secondChild - 1)));
__holeIndex = __secondChild - 1; __holeIndex = __secondChild - 1;
} }
std::__push_heap(__first, __holeIndex, __topIndex, __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
_GLIBCXX_MOVE(__value), __cmp(_GLIBCXX_MOVE(__comp));
__gnu_cxx::__ops:: std::__push_heap(__first, __holeIndex, __topIndex,
__iter_comp_val(_GLIBCXX_MOVE(__comp))); _GLIBCXX_MOVE(__value), __cmp);
} }
template<typename _RandomAccessIterator, typename _Compare> template<typename _RandomAccessIterator, typename _Compare>
inline void inline void
__pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_RandomAccessIterator __result, _Compare __comp) _RandomAccessIterator __result, _Compare& __comp)
{ {
typedef typename iterator_traits<_RandomAccessIterator>::value_type typedef typename iterator_traits<_RandomAccessIterator>::value_type
_ValueType; _ValueType;
...@@ -251,7 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -251,7 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*__result = _GLIBCXX_MOVE(*__first); *__result = _GLIBCXX_MOVE(*__first);
std::__adjust_heap(__first, _DistanceType(0), std::__adjust_heap(__first, _DistanceType(0),
_DistanceType(__last - __first), _DistanceType(__last - __first),
_GLIBCXX_MOVE(__value), _GLIBCXX_MOVE(__comp)); _GLIBCXX_MOVE(__value), __comp);
} }
/** /**
...@@ -282,8 +282,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -282,8 +282,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__last - __first > 1) if (__last - __first > 1)
{ {
--__last; --__last;
std::__pop_heap(__first, __last, __last, __gnu_cxx::__ops::_Iter_less_iter __comp;
__gnu_cxx::__ops::__iter_less_iter()); std::__pop_heap(__first, __last, __last, __comp);
} }
} }
...@@ -313,17 +313,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -313,17 +313,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__last - __first > 1) if (__last - __first > 1)
{ {
using __gnu_cxx::__ops::_Iter_comp_iter;
_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp));
--__last; --__last;
std::__pop_heap(__first, __last, __last, std::__pop_heap(__first, __last, __last, __cmp);
__gnu_cxx::__ops::
__iter_comp_iter(_GLIBCXX_MOVE(__comp)));
} }
} }
template<typename _RandomAccessIterator, typename _Compare> template<typename _RandomAccessIterator, typename _Compare>
void void
__make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp) _Compare& __comp)
{ {
typedef typename iterator_traits<_RandomAccessIterator>::value_type typedef typename iterator_traits<_RandomAccessIterator>::value_type
_ValueType; _ValueType;
...@@ -366,8 +366,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -366,8 +366,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_irreflexive(__first, __last);
std::__make_heap(__first, __last, __gnu_cxx::__ops::_Iter_less_iter __comp;
__gnu_cxx::__ops::__iter_less_iter()); std::__make_heap(__first, __last, __comp);
} }
/** /**
...@@ -391,15 +391,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -391,15 +391,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
std::__make_heap(__first, __last, __gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp));
__gnu_cxx::__ops:: std::__make_heap(__first, __last, __cmp);
__iter_comp_iter(_GLIBCXX_MOVE(__comp)));
} }
template<typename _RandomAccessIterator, typename _Compare> template<typename _RandomAccessIterator, typename _Compare>
void void
__sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp) _Compare& __comp)
{ {
while (__last - __first > 1) while (__last - __first > 1)
{ {
...@@ -429,8 +428,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -429,8 +428,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_irreflexive(__first, __last);
__glibcxx_requires_heap(__first, __last); __glibcxx_requires_heap(__first, __last);
std::__sort_heap(__first, __last, __gnu_cxx::__ops::_Iter_less_iter __comp;
__gnu_cxx::__ops::__iter_less_iter()); std::__sort_heap(__first, __last, __comp);
} }
/** /**
...@@ -455,9 +454,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -455,9 +454,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
__glibcxx_requires_heap_pred(__first, __last, __comp); __glibcxx_requires_heap_pred(__first, __last, __comp);
std::__sort_heap(__first, __last, __gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp));
__gnu_cxx::__ops:: std::__sort_heap(__first, __last, __cmp);
__iter_comp_iter(_GLIBCXX_MOVE(__comp)));
} }
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
...@@ -483,9 +481,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -483,9 +481,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_irreflexive(__first, __last);
__gnu_cxx::__ops::_Iter_less_iter __comp;
return __first + return __first +
std::__is_heap_until(__first, std::distance(__first, __last), std::__is_heap_until(__first, std::distance(__first, __last), __comp);
__gnu_cxx::__ops::__iter_less_iter());
} }
/** /**
...@@ -510,10 +508,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -510,10 +508,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
__gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp));
return __first return __first
+ std::__is_heap_until(__first, std::distance(__first, __last), + std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
__gnu_cxx::__ops::
__iter_comp_iter(std::move(__comp)));
} }
/** /**
...@@ -541,8 +538,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -541,8 +538,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp) _Compare __comp)
{ {
return std::is_heap_until(__first, __last, std::move(__comp)) // concept requirements
== __last; __glibcxx_function_requires(_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
const auto __dist = std::distance(__first, __last);
__gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp));
return std::__is_heap_until(__first, __dist, __cmp) == __dist;
} }
#endif #endif
......
...@@ -32,11 +32,11 @@ struct CopyCounter : std::less<int> ...@@ -32,11 +32,11 @@ struct CopyCounter : std::less<int>
void void
test01() test01()
{ {
int v[] = {1, 2, 3, 4}; int i;
std::priority_queue<int, std::vector<int>, CopyCounter> q{v, v+4}; std::priority_queue<int, std::vector<int>, CopyCounter> q{&i, &i};
VERIFY(count == 4); VERIFY(count == 2);
q.push(1); q.push(1);
VERIFY(count == 5); VERIFY(count == 3);
} }
int int
......
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