From: Jonathan Wakely Date: Thu, 19 Jan 2017 23:07:52 +0000 (+0000) Subject: PR67085 pass comparison functions by reference in heap algorithms X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=437f43cc78d4607e72d7873b64342de2ce2d75cc;p=gcc.git 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): Use converting constructor. (__val_comp_iter(_Iter_comp_iter): 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0106c23a3ef..fde7f341444 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,21 @@ 2017-01-19 Jonathan Wakely + 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): Use converting constructor. + (__val_comp_iter(_Iter_comp_iter): 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. (__make_heap, __sort_heap): Don't use _GLIBCXX_MOVE inside loops. diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h index 2742984b647..a5a7694501a 100644 --- a/libstdc++-v3/include/bits/predefined_ops.h +++ b/libstdc++-v3/include/bits/predefined_ops.h @@ -50,6 +50,15 @@ namespace __ops 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 bool operator()(_Iterator __it, _Value& __val) const @@ -66,6 +75,15 @@ namespace __ops 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 bool operator()(_Value& __val, _Iterator __it) const @@ -141,6 +159,18 @@ namespace __ops : _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 bool operator()(_Iterator __it, _Value& __val) @@ -155,7 +185,7 @@ namespace __ops template inline _Iter_comp_val<_Compare> __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 struct _Val_comp_iter @@ -167,6 +197,18 @@ namespace __ops : _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 bool operator()(_Value& __val, _Iterator __it) @@ -181,7 +223,7 @@ namespace __ops template inline _Val_comp_iter<_Compare> __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 struct _Iter_equals_val diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h index b19c9f499b8..3c102f136e6 100644 --- a/libstdc++-v3/include/bits/stl_heap.h +++ b/libstdc++-v3/include/bits/stl_heap.h @@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename _Compare> _Distance __is_heap_until(_RandomAccessIterator __first, _Distance __n, - _Compare __comp) + _Compare& __comp) { _Distance __parent = 0; for (_Distance __child = 1; __child < __n; ++__child) @@ -91,8 +91,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool __is_heap(_RandomAccessIterator __first, _Distance __n) { - return std::__is_heap_until(__first, __n, - __gnu_cxx::__ops::__iter_less_iter()) == __n; + __gnu_cxx::__ops::_Iter_less_iter __comp; + return std::__is_heap_until(__first, __n, __comp) == __n; } template __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __n, __cmp) == __n; } template @@ -126,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void __push_heap(_RandomAccessIterator __first, _Distance __holeIndex, _Distance __topIndex, _Tp __value, - _Compare __comp) + _Compare& __comp) { _Distance __parent = (__holeIndex - 1) / 2; while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) @@ -165,10 +165,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_heap(__first, __last - 1); + __gnu_cxx::__ops::_Iter_less_val __comp; _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); std::__push_heap(__first, _DistanceType((__last - __first) - 1), - _DistanceType(0), _GLIBCXX_MOVE(__value), - __gnu_cxx::__ops::__iter_less_val()); + _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); } /** @@ -200,11 +200,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive_pred(__first, __last, __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)); std::__push_heap(__first, _DistanceType((__last - __first) - 1), - _DistanceType(0), _GLIBCXX_MOVE(__value), - __gnu_cxx::__ops:: - __iter_comp_val(_GLIBCXX_MOVE(__comp))); + _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp); } template inline void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _RandomAccessIterator __result, _Compare __comp) + _RandomAccessIterator __result, _Compare& __comp) { typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; @@ -251,7 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION *__result = _GLIBCXX_MOVE(*__first); std::__adjust_heap(__first, _DistanceType(0), _DistanceType(__last - __first), - _GLIBCXX_MOVE(__value), _GLIBCXX_MOVE(__comp)); + _GLIBCXX_MOVE(__value), __comp); } /** @@ -282,8 +282,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__last - __first > 1) { --__last; - std::__pop_heap(__first, __last, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__pop_heap(__first, __last, __last, __comp); } } @@ -313,17 +313,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__last - __first > 1) { + using __gnu_cxx::__ops::_Iter_comp_iter; + _Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp)); --__last; - std::__pop_heap(__first, __last, __last, - __gnu_cxx::__ops:: - __iter_comp_iter(_GLIBCXX_MOVE(__comp))); + std::__pop_heap(__first, __last, __last, __cmp); } } template void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) + _Compare& __comp) { typedef typename iterator_traits<_RandomAccessIterator>::value_type _ValueType; @@ -366,8 +366,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - std::__make_heap(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__make_heap(__first, __last, __comp); } /** @@ -391,15 +391,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - std::__make_heap(__first, __last, - __gnu_cxx::__ops:: - __iter_comp_iter(_GLIBCXX_MOVE(__comp))); + __gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp)); + std::__make_heap(__first, __last, __cmp); } template void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) + _Compare& __comp) { while (__last - __first > 1) { @@ -429,8 +428,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_heap(__first, __last); - std::__sort_heap(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__sort_heap(__first, __last, __comp); } /** @@ -455,9 +454,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_heap_pred(__first, __last, __comp); - std::__sort_heap(__first, __last, - __gnu_cxx::__ops:: - __iter_comp_iter(_GLIBCXX_MOVE(__comp))); + __gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp)); + std::__sort_heap(__first, __last, __cmp); } #if __cplusplus >= 201103L @@ -483,9 +481,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); + __gnu_cxx::__ops::_Iter_less_iter __comp; return __first + - std::__is_heap_until(__first, std::distance(__first, __last), - __gnu_cxx::__ops::__iter_less_iter()); + std::__is_heap_until(__first, std::distance(__first, __last), __comp); } /** @@ -510,10 +508,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __gnu_cxx::__ops::_Iter_comp_iter<_Compare> __cmp(_GLIBCXX_MOVE(__comp)); return __first - + std::__is_heap_until(__first, std::distance(__first, __last), - __gnu_cxx::__ops:: - __iter_comp_iter(std::move(__comp))); + + std::__is_heap_until(__first, std::distance(__first, __last), __cmp); } /** @@ -541,8 +538,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - return std::is_heap_until(__first, __last, std::move(__comp)) - == __last; + // concept requirements + __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 diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/67085.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/67085.cc index 4ccea309fcf..9f4da585dd8 100644 --- a/libstdc++-v3/testsuite/23_containers/priority_queue/67085.cc +++ b/libstdc++-v3/testsuite/23_containers/priority_queue/67085.cc @@ -32,11 +32,11 @@ struct CopyCounter : std::less void test01() { - int v[] = {1, 2, 3, 4}; - std::priority_queue, CopyCounter> q{v, v+4}; - VERIFY(count == 4); + int i; + std::priority_queue, CopyCounter> q{&i, &i}; + VERIFY(count == 2); q.push(1); - VERIFY(count == 5); + VERIFY(count == 3); } int