This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Remove algo duplications
- From: François Dumont <frs dot dumont at gmail dot com>
- To: "libstdc++ at gcc dot gnu dot org" <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 12 Jun 2012 22:05:41 +0200
- Subject: Remove algo duplications
Hi
Here is a new version of the patch to remove duplication of algo
implementations.
Compared to the previous version I have rename functors that apply
to iterators (iter_less, iter_equal_to). I have also added move
semantics when iterator dereference operator returns anything except
lvalue reference (rvalue reference or an instance).
2012-06-12 François Dumont <fdumont@gcc.gnu.org>
* include/bits/predefined_ops.h: New. Internal functors use to
avoid algorithm duplications.
* include/bits/stl_algobase.h, stl_algo.h, stl_heap.h: Adapt to
use latter functors, remove many algorithm duplications.
* testsuite/util/testsuite_counter_type.h: New.
* testsuite/25_algorithms/lower_bound/3.cc, 4.cc: New.
I don't think tests are to be added. They are not really tests but
rather use cases to experiment impact of the patch in different
situtations, with/without -fno-elide-constructors, in C++ 11 or C++98.
You can see in those the impact of the patch which is more or less what
Marc Glisse already remarked. You can see an impact mostly when the
iterator::reference type is not a reference, there are additional copies
then. But I still think this patch make sens cause it greatly simplify
library code.
Tested under linux x86_64.
François
Index: include/Makefile.in
===================================================================
--- include/Makefile.in (revision 188314)
+++ include/Makefile.in (working copy)
@@ -391,6 +391,7 @@
${bits_srcdir}/shared_ptr_base.h \
${bits_srcdir}/slice_array.h \
${bits_srcdir}/sstream.tcc \
+ ${bits_srcdir}/predefined_ops.h \
${bits_srcdir}/stl_algo.h \
${bits_srcdir}/stl_algobase.h \
${bits_srcdir}/stl_bvector.h \
Index: include/bits/stl_algobase.h
===================================================================
--- include/bits/stl_algobase.h (revision 188314)
+++ include/bits/stl_algobase.h (working copy)
@@ -69,6 +69,7 @@
#include <bits/concept_check.h>
#include <debug/debug.h>
#include <bits/move.h> // For std::swap and _GLIBCXX_MOVE
+#include <bits/predefined_ops.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -864,6 +865,29 @@
{ return true; }
};
+ template<typename _II1, typename _II2,
+ typename _Compare12, typename _Compare21>
+ bool
+ __lexicographical_compare_impl(_II1 __first1, _II1 __last1,
+ _II2 __first2, _II2 __last2,
+ _Compare12 __comp12, _Compare21 __comp21)
+ {
+ typedef typename iterator_traits<_II1>::iterator_category _Category1;
+ typedef typename iterator_traits<_II2>::iterator_category _Category2;
+ typedef std::__lc_rai<_Category1, _Category2> __rai_type;
+
+ __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2);
+ for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
+ ++__first1, ++__first2)
+ {
+ if (__comp12(*__first1, *__first2))
+ return true;
+ if (__comp21(*__first2, *__first1))
+ return false;
+ }
+ return __first1 == __last1 && __first2 != __last2;
+ }
+
template<bool _BoolType>
struct __lexicographical_compare
{
@@ -877,21 +901,10 @@
__lexicographical_compare<_BoolType>::
__lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2)
{
- typedef typename iterator_traits<_II1>::iterator_category _Category1;
- typedef typename iterator_traits<_II2>::iterator_category _Category2;
- typedef std::__lc_rai<_Category1, _Category2> __rai_type;
-
- __last1 = __rai_type::__newlast1(__first1, __last1,
- __first2, __last2);
- for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
- ++__first1, ++__first2)
- {
- if (*__first1 < *__first2)
- return true;
- if (*__first2 < *__first1)
- return false;
- }
- return __first1 == __last1 && __first2 != __last2;
+ return std::__lexicographical_compare_impl(
+ __first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::iter_less<_II1, _II2>(),
+ __gnu_cxx::__ops::iter_less<_II2, _II1>());
}
template<>
@@ -928,34 +941,14 @@
__first2, __last2);
}
- /**
- * @brief Finds the first position in which @a val could be inserted
- * without changing the ordering.
- * @param __first An iterator.
- * @param __last Another iterator.
- * @param __val The search term.
- * @return An iterator pointing to the first element <em>not less
- * than</em> @a val, or end() if every element is less than
- * @a val.
- * @ingroup binary_search_algorithms
- */
- template<typename _ForwardIterator, typename _Tp>
+ template<typename _ForwardIterator, typename _Tp, typename _Compare>
_ForwardIterator
- lower_bound(_ForwardIterator __first, _ForwardIterator __last,
- const _Tp& __val)
+ __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val, _Compare __comp)
{
-#ifdef _GLIBCXX_CONCEPT_CHECKS
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-#endif
typedef typename iterator_traits<_ForwardIterator>::difference_type
_DistanceType;
- // concept requirements
- __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType, _Tp>)
- __glibcxx_requires_partitioned_lower(__first, __last, __val);
-
_DistanceType __len = std::distance(__first, __last);
while (__len > 0)
@@ -963,7 +956,7 @@
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (*__middle < __val)
+ if (__comp(*__middle, __val))
{
__first = __middle;
++__first;
@@ -975,6 +968,36 @@
return __first;
}
+ /**
+ * @brief Finds the first position in which @a val could be inserted
+ * without changing the ordering.
+ * @param __first An iterator.
+ * @param __last Another iterator.
+ * @param __val The search term.
+ * @return An iterator pointing to the first element <em>not less
+ * than</em> @a val, or end() if every element is less than
+ * @a val.
+ * @ingroup binary_search_algorithms
+ */
+ template<typename _ForwardIterator, typename _Tp>
+ _ForwardIterator
+ lower_bound(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val)
+ {
+ typedef iterator_traits<_ForwardIterator> _ItTraits;
+
+ // concept requirements
+ __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
+ __glibcxx_function_requires(
+ _LessThanOpConcept<typename _ItTraits::value_type, _Tp>)
+ __glibcxx_requires_partitioned_lower(__first, __last, __val);
+
+ return std::__lower_bound(__first, __last, __val,
+ __gnu_cxx::__ops
+ ::less<typename _ItTraits::reference,
+ const _Tp&>());
+ }
+
/// This is a helper function for the sort routines and for random.tcc.
// Precondition: __n > 0.
inline _GLIBCXX_CONSTEXPR int
@@ -1121,28 +1144,31 @@
lexicographical_compare(_II1 __first1, _II1 __last1,
_II2 __first2, _II2 __last2, _Compare __comp)
{
- typedef typename iterator_traits<_II1>::iterator_category _Category1;
- typedef typename iterator_traits<_II2>::iterator_category _Category2;
- typedef std::__lc_rai<_Category1, _Category2> __rai_type;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_II1>)
__glibcxx_function_requires(_InputIteratorConcept<_II2>)
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2);
- for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
- ++__first1, ++__first2)
- {
- if (__comp(*__first1, *__first2))
- return true;
- if (__comp(*__first2, *__first1))
- return false;
- }
- return __first1 == __last1 && __first2 != __last2;
+ return std::__lexicographical_compare_impl(__first1, __last1,
+ __first2, __last2,
+ __comp, __comp);
}
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _BinaryPredicate>
+ pair<_InputIterator1, _InputIterator2>
+ __mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _BinaryPredicate __binary_pred)
+ {
+ while (__first1 != __last1 && bool(__binary_pred(*__first1, *__first2)))
+ {
+ ++__first1;
+ ++__first2;
+ }
+ return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
+ }
+
/**
* @brief Finds the places in ranges which don't match.
* @ingroup non_mutating_algorithms
@@ -1169,12 +1195,9 @@
typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_requires_valid_range(__first1, __last1);
- while (__first1 != __last1 && *__first1 == *__first2)
- {
- ++__first1;
- ++__first2;
- }
- return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
+ return std::__mismatch(__first1, __last1, __first2,
+ __gnu_cxx::__ops::iter_equal_to<_InputIterator1,
+ _InputIterator2>());
}
/**
@@ -1204,12 +1227,7 @@
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_requires_valid_range(__first1, __last1);
- while (__first1 != __last1 && bool(__binary_pred(*__first1, *__first2)))
- {
- ++__first1;
- ++__first2;
- }
- return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
+ return std::__mismatch(__first1, __last1, __first2, __binary_pred);
}
_GLIBCXX_END_NAMESPACE_ALGO
Index: include/bits/stl_heap.h
===================================================================
--- include/bits/stl_heap.h (revision 188314)
+++ include/bits/stl_heap.h (working copy)
@@ -58,6 +58,7 @@
#include <debug/debug.h>
#include <bits/move.h>
+#include <bits/predefined_ops.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -68,21 +69,6 @@
* @ingroup sorting_algorithms
*/
- template<typename _RandomAccessIterator, typename _Distance>
- _Distance
- __is_heap_until(_RandomAccessIterator __first, _Distance __n)
- {
- _Distance __parent = 0;
- for (_Distance __child = 1; __child < __n; ++__child)
- {
- if (__first[__parent] < __first[__child])
- return __child;
- if ((__child & 1) == 0)
- ++__parent;
- }
- return __n;
- }
-
template<typename _RandomAccessIterator, typename _Distance,
typename _Compare>
_Distance
@@ -105,7 +91,11 @@
template<typename _RandomAccessIterator, typename _Distance>
inline bool
__is_heap(_RandomAccessIterator __first, _Distance __n)
- { return std::__is_heap_until(__first, __n) == __n; }
+ {
+ return std::__is_heap_until(__first, __n,
+ __gnu_cxx::__ops
+ ::iter_less<_RandomAccessIterator>()) == __n;
+ }
template<typename _RandomAccessIterator, typename _Compare,
typename _Distance>
@@ -127,13 +117,15 @@
// Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
// + is_heap and is_heap_until in C++0x.
- template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
+ template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
+ typename _Compare>
void
- __push_heap(_RandomAccessIterator __first,
- _Distance __holeIndex, _Distance __topIndex, _Tp __value)
+ __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
+ _Distance __topIndex, _Tp __value, _Compare __comp)
{
_Distance __parent = (__holeIndex - 1) / 2;
- while (__holeIndex > __topIndex && *(__first + __parent) < __value)
+ while (__holeIndex > __topIndex
+ && __comp(*(__first + __parent), __value))
{
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
__holeIndex = __parent;
@@ -156,10 +148,9 @@
inline void
push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
+ typedef iterator_traits<_RandomAccessIterator> _ItTraits;
+ typedef typename _ItTraits::value_type _ValueType;
+ typedef typename _ItTraits::difference_type _DistanceType;
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
@@ -170,26 +161,12 @@
_ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
std::__push_heap(__first, _DistanceType((__last - __first) - 1),
- _DistanceType(0), _GLIBCXX_MOVE(__value));
+ _DistanceType(0), _GLIBCXX_MOVE(__value),
+ __gnu_cxx::__ops
+ ::less<typename _ItTraits::reference,
+ _ValueType&>());
}
- template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
- typename _Compare>
- void
- __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
- _Distance __topIndex, _Tp __value, _Compare __comp)
- {
- _Distance __parent = (__holeIndex - 1) / 2;
- while (__holeIndex > __topIndex
- && __comp(*(__first + __parent), __value))
- {
- *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
- __holeIndex = __parent;
- __parent = (__holeIndex - 1) / 2;
- }
- *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
- }
-
/**
* @brief Push an element onto a heap using comparison functor.
* @param __first Start of heap.
@@ -223,17 +200,19 @@
_DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
}
- template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
+ template<typename _RandomAccessIterator, typename _Distance,
+ typename _Tp, typename _Compare>
void
__adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
- _Distance __len, _Tp __value)
+ _Distance __len, _Tp __value, _Compare __comp)
{
const _Distance __topIndex = __holeIndex;
_Distance __secondChild = __holeIndex;
while (__secondChild < (__len - 1) / 2)
{
__secondChild = 2 * (__secondChild + 1);
- if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
+ if (__comp(*(__first + __secondChild),
+ *(__first + (__secondChild - 1))))
__secondChild--;
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
__holeIndex = __secondChild;
@@ -245,14 +224,19 @@
+ (__secondChild - 1)));
__holeIndex = __secondChild - 1;
}
- std::__push_heap(__first, __holeIndex, __topIndex,
- _GLIBCXX_MOVE(__value));
+ typedef iterator_traits<_RandomAccessIterator> _ItTraits;
+ std::__push_heap(__first, __holeIndex, __topIndex,
+ _GLIBCXX_MOVE(__value),
+ __gnu_cxx::__ops
+ ::_RebindHelper<typename _ItTraits::reference,
+ _Tp&>
+ ::rebind(__comp));
}
- template<typename _RandomAccessIterator>
+ template<typename _RandomAccessIterator, typename _Compare>
inline void
__pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _RandomAccessIterator __result)
+ _RandomAccessIterator __result, _Compare __comp)
{
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_ValueType;
@@ -263,7 +247,7 @@
*__result = _GLIBCXX_MOVE(*__first);
std::__adjust_heap(__first, _DistanceType(0),
_DistanceType(__last - __first),
- _GLIBCXX_MOVE(__value));
+ _GLIBCXX_MOVE(__value), __comp);
}
/**
@@ -293,54 +277,10 @@
__glibcxx_requires_heap(__first, __last);
--__last;
- std::__pop_heap(__first, __last, __last);
+ std::__pop_heap(__first, __last, __last,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
}
- template<typename _RandomAccessIterator, typename _Distance,
- typename _Tp, typename _Compare>
- void
- __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
- _Distance __len, _Tp __value, _Compare __comp)
- {
- const _Distance __topIndex = __holeIndex;
- _Distance __secondChild = __holeIndex;
- while (__secondChild < (__len - 1) / 2)
- {
- __secondChild = 2 * (__secondChild + 1);
- if (__comp(*(__first + __secondChild),
- *(__first + (__secondChild - 1))))
- __secondChild--;
- *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
- __holeIndex = __secondChild;
- }
- if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
- {
- __secondChild = 2 * (__secondChild + 1);
- *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
- + (__secondChild - 1)));
- __holeIndex = __secondChild - 1;
- }
- std::__push_heap(__first, __holeIndex, __topIndex,
- _GLIBCXX_MOVE(__value), __comp);
- }
-
- template<typename _RandomAccessIterator, typename _Compare>
- inline void
- __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _RandomAccessIterator __result, _Compare __comp)
- {
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
-
- _ValueType __value = _GLIBCXX_MOVE(*__result);
- *__result = _GLIBCXX_MOVE(*__first);
- std::__adjust_heap(__first, _DistanceType(0),
- _DistanceType(__last - __first),
- _GLIBCXX_MOVE(__value), __comp);
- }
-
/**
* @brief Pop an element off a heap using comparison functor.
* @param __first Start of heap.
@@ -368,6 +308,32 @@
std::__pop_heap(__first, __last, __last, __comp);
}
+ template<typename _RandomAccessIterator, typename _Compare>
+ void
+ __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_RandomAccessIterator>::value_type
+ _ValueType;
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+ _DistanceType;
+
+ if (__last - __first < 2)
+ return;
+
+ const _DistanceType __len = __last - __first;
+ _DistanceType __parent = (__len - 2) / 2;
+ while (true)
+ {
+ _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
+ std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
+ __comp);
+ if (__parent == 0)
+ return;
+ __parent--;
+ }
+ }
+
/**
* @brief Construct a heap over a range.
* @param __first Start of heap.
@@ -391,19 +357,8 @@
__glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
- if (__last - __first < 2)
- return;
-
- const _DistanceType __len = __last - __first;
- _DistanceType __parent = (__len - 2) / 2;
- while (true)
- {
- _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
- std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value));
- if (__parent == 0)
- return;
- __parent--;
- }
+ std::__make_heap(__first, __last,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
}
/**
@@ -431,19 +386,18 @@
_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
- if (__last - __first < 2)
- return;
+ std::__make_heap(__first, __last, __comp);
+ }
- const _DistanceType __len = __last - __first;
- _DistanceType __parent = (__len - 2) / 2;
- while (true)
+ template<typename _RandomAccessIterator, typename _Compare>
+ void
+ __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
+ {
+ while (__last - __first > 1)
{
- _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
- std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
- __comp);
- if (__parent == 0)
- return;
- __parent--;
+ --__last;
+ std::__pop_heap(__first, __last, __last, __comp);
}
}
@@ -467,11 +421,8 @@
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_heap(__first, __last);
- while (__last - __first > 1)
- {
- --__last;
- std::__pop_heap(__first, __last, __last);
- }
+ __sort_heap(__first, __last,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
}
/**
@@ -495,11 +446,7 @@
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_heap_pred(__first, __last, __comp);
- while (__last - __first > 1)
- {
- --__last;
- std::__pop_heap(__first, __last, __last, __comp);
- }
+ __sort_heap(__first, __last, __comp);
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
@@ -517,15 +464,21 @@
inline _RandomAccessIterator
is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
+ typedef iterator_traits<_RandomAccessIterator> _ItTraits;
+
// concept requirements
__glibcxx_function_requires(_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_LessThanComparableConcept<
- typename iterator_traits<_RandomAccessIterator>::value_type>)
+ typename _ItTraits::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return __first + std::__is_heap_until(__first, std::distance(__first,
- __last));
+ return __first +
+ std::__is_heap_until(__first,
+ std::distance(__first, __last),
+ [](typename _ItTraits::reference __lhs,
+ typename _ItTraits::reference __rhs)
+ { return __lhs < __rhs; });
}
/**
@@ -549,8 +502,8 @@
_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
- return __first + std::__is_heap_until(__first, std::distance(__first,
- __last),
+ return __first + std::__is_heap_until(__first,
+ std::distance(__first, __last),
__comp);
}
Index: include/bits/predefined_ops.h
===================================================================
--- include/bits/predefined_ops.h (revision 0)
+++ include/bits/predefined_ops.h (revision 0)
@@ -0,0 +1,342 @@
+// Default predicates for internal use -*- C++ -*-
+
+// Copyright (C) 2012 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file predefined_ops.h
+ * This is an internal header file, included by other library headers.
+ * You should not attempt to use it directly.
+ */
+
+#ifndef _GLIBCXX_PREDEFINED_OPS_H
+#define _GLIBCXX_PREDEFINED_OPS_H 1
+
+namespace __gnu_cxx
+{
+namespace __ops
+{
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Lhs, typename _Rhs>
+#else
+ template<typename _Lhs, typename _Rhs,
+ bool = std::is_lvalue_reference<_Lhs>::value,
+ bool = std::is_lvalue_reference<_Rhs>::value>
+#endif
+ struct less
+ {
+ bool
+ operator()(_Lhs __lhs, _Rhs __rhs) /* Not const so that we do not force
+ the < operator to be const
+ qualified. */
+ { return __lhs < __rhs; }
+ };
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ /* As soon as the less functor is passing a parameter per value or per rvalue
+ reference type, that is to say not per lvalue reference, we implement the
+ move semantic logic. */
+ template<typename _Lhs, typename _Rhs>
+ struct less<_Lhs, _Rhs, false, true>
+ {
+ bool
+ operator()(_Lhs&& __lhs, _Rhs __rhs)
+ { return std::forward<_Lhs>(__lhs) < __rhs; }
+ };
+
+ template<typename _Lhs, typename _Rhs>
+ struct less<_Lhs, _Rhs, true, false>
+ {
+ bool
+ operator()(_Lhs __lhs, _Rhs&& __rhs)
+ { return __lhs < std::forward<_Rhs>(__rhs); }
+ };
+
+ template<typename _Lhs, typename _Rhs>
+ struct less<_Lhs, _Rhs, false, false>
+ {
+ bool
+ operator()(_Lhs&& __lhs, _Rhs&& __rhs)
+ { return std::forward<_Lhs>(__lhs) < std::forward<_Rhs>(__rhs); }
+ };
+#endif
+
+ template<typename _Iterator1, typename _Iterator2 = _Iterator1>
+ struct iter_less
+ : less<typename std::iterator_traits<_Iterator1>::reference,
+ typename std::iterator_traits<_Iterator2>::reference>
+ { };
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Lhs, typename _Rhs>
+#else
+ template<typename _Lhs, typename _Rhs,
+ bool = std::is_lvalue_reference<_Lhs>::value,
+ bool = std::is_lvalue_reference<_Rhs>::value>
+#endif
+ struct equal_to
+ {
+ bool
+ operator()(_Lhs __lhs, _Rhs __rhs) /* Not const so that we do not force
+ the == operator to be const
+ qualified. */
+ { return __lhs == __rhs; }
+ };
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Lhs, typename _Rhs>
+ struct equal_to<_Lhs, _Rhs, false, true>
+ {
+ bool
+ operator()(_Lhs&& __lhs, _Rhs __rhs)
+ { return std::forward<_Lhs>(__lhs) == __rhs; }
+ };
+
+ template<typename _Lhs, typename _Rhs>
+ struct equal_to<_Lhs, _Rhs, true, false>
+ {
+ bool
+ operator()(_Lhs __lhs, _Rhs&& __rhs)
+ { return __lhs == std::forward<_Rhs>(__rhs); }
+ };
+
+ template<typename _Lhs, typename _Rhs>
+ struct equal_to<_Lhs, _Rhs, false, false>
+ {
+ bool
+ operator()(_Lhs&& __lhs, _Rhs&& __rhs)
+ { return std::forward<_Lhs>(__lhs) == std::forward<_Rhs>(__rhs); }
+ };
+#endif
+
+ template<typename _Iterator1, typename _Iterator2 = _Iterator1>
+ struct iter_equal_to
+ : equal_to<typename std::iterator_traits<_Iterator1>::reference,
+ typename std::iterator_traits<_Iterator2>::reference>
+ { };
+
+ template<typename _Iterator, typename _Value>
+ struct iter_equal_to_val
+ : equal_to<typename std::iterator_traits<_Iterator>::reference,
+ const _Value&>
+ { };
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Iterator, typename _Pred>
+#else
+ template<typename _Iterator, typename _Pred,
+ bool = std::is_lvalue_reference<typename _Iterator::reference>::value>
+#endif
+ struct __negate
+ {
+ typedef typename std::iterator_traits<_Iterator>::reference _Ref;
+
+ _Pred _M_pred;
+
+ __negate(_Pred __pred) : _M_pred(__pred)
+ { }
+
+ bool
+ operator()(_Ref __x) /* Not const so that we do not force the predicate
+ to be const qualified. */
+ { return !bool(_M_pred(__x)); }
+ };
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Iterator, typename _Pred>
+ struct __negate<_Iterator, _Pred, false>
+ {
+ typedef typename std::iterator_traits<_Iterator>::reference _Ref;
+
+ _Pred _M_pred;
+
+ __negate(_Pred __pred) : _M_pred(__pred)
+ { }
+
+ bool
+ operator()(_Ref&& __x) /* Not const so that we do not force the predicate
+ to be const qualified. */
+ { return !bool(_M_pred(std::forward<_Ref>(__x))); }
+ };
+#endif
+
+ /**
+ * @if maint
+ * A class inspired by bind2nd and company, which wraps a function or
+ * class and a reference, and produces a unary function object. It has less
+ * requirements than the standard version and is designed to be use to wrap
+ * binary predicates given to algorithms in the standard library.
+ * @endif
+ */
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Iterator, typename _Pred, typename _Value>
+#else
+ template<typename _Iterator, typename _Pred, typename _Value,
+ bool = std::is_lvalue_reference<typename _Iterator::reference>::value>
+#endif
+ class __bind2nd
+ {
+ _Pred _M_pred;
+ const _Value& _M_rhs;
+
+ typedef typename std::iterator_traits<_Iterator>::reference _Ref;
+
+ public:
+ __bind2nd(_Pred __pred, const _Value& __rhs)
+ : _M_pred(__pred), _M_rhs(__rhs) {}
+
+ bool
+ operator()(_Ref __lhs) /* Not const so that we do not force the predicate
+ to be const qualified. */
+ { return _M_pred(__lhs, _M_rhs); }
+ };
+
+ /**
+ * @if maint
+ * Specialisation of __bind2nd for equality.
+ * @endif
+ */
+ template<typename _Iterator, typename _Value,
+ typename _Iterator1, typename _Iterator2>
+ class __bind2nd<_Iterator,
+ __gnu_cxx::__ops::iter_equal_to<_Iterator1, _Iterator2>,
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ _Value>
+#else
+ _Value, true>
+#endif
+ {
+ const _Value& _M_rhs;
+
+ typedef typename std::iterator_traits<_Iterator>::reference _Ref;
+
+ public:
+ __bind2nd(__gnu_cxx::__ops::iter_equal_to<_Iterator1, _Iterator2>,
+ const _Value& __rhs)
+ : _M_rhs(__rhs) {}
+
+ bool
+ operator()(_Ref __lhs) /* Not const so that we do not force the ==
+ operator to be const qualified. */
+ { return __lhs == _M_rhs; }
+ };
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ template<typename _Iterator, typename _Pred, typename _Value>
+ class __bind2nd<_Iterator, _Pred, _Value, false>
+ {
+ _Pred _M_pred;
+ const _Value& _M_rhs;
+
+ typedef typename std::iterator_traits<_Iterator>::reference _Ref;
+
+ public:
+ __bind2nd(_Pred __pred, const _Value& __rhs)
+ : _M_pred(__pred), _M_rhs(__rhs) {}
+
+ bool
+ operator()(_Ref&& __lhs) /* Not const so that we do not force the predicate
+ to be const qualified. */
+ { return _M_pred(std::forward<_Ref>(__lhs), _M_rhs); }
+ };
+
+ template<typename _Iterator, typename _Value,
+ typename _Iterator1, typename _Iterator2>
+ class __bind2nd<_Iterator,
+ __gnu_cxx::__ops::iter_equal_to<_Iterator1, _Iterator2>,
+ _Value, false>
+ {
+ const _Value& _M_rhs;
+
+ typedef typename std::iterator_traits<_Iterator>::reference _Ref;
+
+ public:
+ __bind2nd(__gnu_cxx::__ops::iter_equal_to<_Iterator1, _Iterator2>,
+ const _Value& __rhs)
+ : _M_rhs(__rhs) {}
+
+ bool
+ operator()(_Ref&& __lhs) /* Not const so that we do not force the ==
+ operator to be const qualified. */
+ { return std::forward<_Ref>(__lhs) == _M_rhs; }
+ };
+#endif
+
+ template<typename _Iterator>
+ struct _Adapters
+ {
+ template<typename _Pred, typename _Value>
+ static __bind2nd<_Iterator, _Pred, _Value>
+ bind2nd(_Pred __pred, const _Value& __val)
+ { return __bind2nd<_Iterator, _Pred, _Value>(__pred, __val); }
+
+ template<typename _Pred>
+ static __negate<_Iterator, _Pred>
+ negate(_Pred __pred)
+ { return __negate<_Iterator, _Pred>(__pred); }
+ };
+
+ template<typename _Lhs, typename _Rhs>
+ struct _RebindHelper
+ {
+ private:
+ template<typename _Pred>
+ struct _NestedHelper
+ {
+ typedef _Pred _Ret;
+
+ static _Ret
+ rebind(_Pred __pred)
+ { return __pred; }
+ };
+
+ template<typename _Ref1, typename _Ref2>
+ struct _NestedHelper<__gnu_cxx::__ops::less<_Ref1, _Ref2> >
+ {
+ typedef __gnu_cxx::__ops::less<_Lhs, _Rhs> _Ret;
+
+ static _Ret
+ rebind(__gnu_cxx::__ops::less<_Ref1, _Ref2>)
+ { return _Ret(); }
+ };
+
+ template<typename _Iterator1, typename _Iterator2>
+ struct _NestedHelper<__gnu_cxx::__ops::iter_less<_Iterator1,
+ _Iterator2> >
+ {
+ typedef __gnu_cxx::__ops::less<_Lhs, _Rhs> _Ret;
+
+ static _Ret
+ rebind(__gnu_cxx::__ops::iter_less<_Iterator1, _Iterator2>)
+ { return _Ret(); }
+ };
+
+ public:
+ template <typename _Pred>
+ static typename _NestedHelper<_Pred>::_Ret
+ rebind(_Pred __pred)
+ { return _NestedHelper<_Pred>::rebind(__pred); }
+ };
+
+} // namespace __ops
+} // namespace __gnu_cxx
+
+#endif
Property changes on: include/bits/predefined_ops.h
___________________________________________________________________
Added: svn:eol-style
+ native
Index: include/bits/stl_algo.h
===================================================================
--- include/bits/stl_algo.h (revision 188314)
+++ include/bits/stl_algo.h (working copy)
@@ -62,6 +62,7 @@
#include <bits/algorithmfwd.h>
#include <bits/stl_heap.h>
#include <bits/stl_tempbuf.h> // for _Temporary_buffer
+#include <bits/predefined_ops.h>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <random> // for std::uniform_int_distribution
@@ -74,30 +75,6 @@
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- /// Swaps the median value of *__a, *__b and *__c to *__a
- template<typename _Iterator>
- void
- __move_median_first(_Iterator __a, _Iterator __b, _Iterator __c)
- {
- // concept requirements
- __glibcxx_function_requires(_LessThanComparableConcept<
- typename iterator_traits<_Iterator>::value_type>)
-
- if (*__a < *__b)
- {
- if (*__b < *__c)
- std::iter_swap(__a, __b);
- else if (*__a < *__c)
- std::iter_swap(__a, __c);
- }
- else if (*__a < *__c)
- return;
- else if (*__b < *__c)
- std::iter_swap(__a, __c);
- else
- std::iter_swap(__a, __b);
- }
-
/// Swaps the median value of *__a, *__b and *__c under __comp to *__a
template<typename _Iterator, typename _Compare>
void
@@ -126,17 +103,6 @@
// for_each
- /// This is an overload used by find() for the Input Iterator case.
- template<typename _InputIterator, typename _Tp>
- inline _InputIterator
- __find(_InputIterator __first, _InputIterator __last,
- const _Tp& __val, input_iterator_tag)
- {
- while (__first != __last && !(*__first == __val))
- ++__first;
- return __first;
- }
-
/// This is an overload used by find_if() for the Input Iterator case.
template<typename _InputIterator, typename _Predicate>
inline _InputIterator
@@ -148,54 +114,6 @@
return __first;
}
- /// This is an overload used by find() for the RAI case.
- template<typename _RandomAccessIterator, typename _Tp>
- _RandomAccessIterator
- __find(_RandomAccessIterator __first, _RandomAccessIterator __last,
- const _Tp& __val, random_access_iterator_tag)
- {
- typename iterator_traits<_RandomAccessIterator>::difference_type
- __trip_count = (__last - __first) >> 2;
-
- for (; __trip_count > 0; --__trip_count)
- {
- if (*__first == __val)
- return __first;
- ++__first;
-
- if (*__first == __val)
- return __first;
- ++__first;
-
- if (*__first == __val)
- return __first;
- ++__first;
-
- if (*__first == __val)
- return __first;
- ++__first;
- }
-
- switch (__last - __first)
- {
- case 3:
- if (*__first == __val)
- return __first;
- ++__first;
- case 2:
- if (*__first == __val)
- return __first;
- ++__first;
- case 1:
- if (*__first == __val)
- return __first;
- ++__first;
- case 0:
- default:
- return __last;
- }
- }
-
/// This is an overload used by find_if() for the RAI case.
template<typename _RandomAccessIterator, typename _Predicate>
_RandomAccessIterator
@@ -244,73 +162,16 @@
}
}
- /// This is an overload used by find_if_not() for the Input Iterator case.
- template<typename _InputIterator, typename _Predicate>
- inline _InputIterator
- __find_if_not(_InputIterator __first, _InputIterator __last,
- _Predicate __pred, input_iterator_tag)
- {
- while (__first != __last && bool(__pred(*__first)))
- ++__first;
- return __first;
- }
-
- /// This is an overload used by find_if_not() for the RAI case.
- template<typename _RandomAccessIterator, typename _Predicate>
- _RandomAccessIterator
- __find_if_not(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _Predicate __pred, random_access_iterator_tag)
- {
- typename iterator_traits<_RandomAccessIterator>::difference_type
- __trip_count = (__last - __first) >> 2;
-
- for (; __trip_count > 0; --__trip_count)
- {
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
-
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
-
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
-
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- }
-
- switch (__last - __first)
- {
- case 3:
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- case 2:
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- case 1:
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- case 0:
- default:
- return __last;
- }
- }
-
/// Provided for stable_partition to use.
template<typename _InputIterator, typename _Predicate>
inline _InputIterator
__find_if_not(_InputIterator __first, _InputIterator __last,
_Predicate __pred)
{
- return std::__find_if_not(__first, __last, __pred,
- std::__iterator_category(__first));
+ return std::__find_if(__first, __last,
+ __gnu_cxx::__ops
+ ::_Adapters<_InputIterator>::negate(__pred),
+ std::__iterator_category(__first));
}
/// Like find_if_not(), but uses and updates a count of the
@@ -339,88 +200,6 @@
// count_if
// search
- /**
- * This is an uglified
- * search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&)
- * overloaded for forward iterators.
- */
- template<typename _ForwardIterator, typename _Integer, typename _Tp>
- _ForwardIterator
- __search_n(_ForwardIterator __first, _ForwardIterator __last,
- _Integer __count, const _Tp& __val,
- std::forward_iterator_tag)
- {
- __first = _GLIBCXX_STD_A::find(__first, __last, __val);
- while (__first != __last)
- {
- typename iterator_traits<_ForwardIterator>::difference_type
- __n = __count;
- _ForwardIterator __i = __first;
- ++__i;
- while (__i != __last && __n != 1 && *__i == __val)
- {
- ++__i;
- --__n;
- }
- if (__n == 1)
- return __first;
- if (__i == __last)
- return __last;
- __first = _GLIBCXX_STD_A::find(++__i, __last, __val);
- }
- return __last;
- }
-
- /**
- * This is an uglified
- * search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&)
- * overloaded for random access iterators.
- */
- template<typename _RandomAccessIter, typename _Integer, typename _Tp>
- _RandomAccessIter
- __search_n(_RandomAccessIter __first, _RandomAccessIter __last,
- _Integer __count, const _Tp& __val,
- std::random_access_iterator_tag)
- {
-
- typedef typename std::iterator_traits<_RandomAccessIter>::difference_type
- _DistanceType;
-
- _DistanceType __tailSize = __last - __first;
- const _DistanceType __pattSize = __count;
-
- if (__tailSize < __pattSize)
- return __last;
-
- const _DistanceType __skipOffset = __pattSize - 1;
- _RandomAccessIter __lookAhead = __first + __skipOffset;
- __tailSize -= __pattSize;
-
- while (1) // the main loop...
- {
- // __lookAhead here is always pointing to the last element of next
- // possible match.
- while (!(*__lookAhead == __val)) // the skip loop...
- {
- if (__tailSize < __pattSize)
- return __last; // Failure
- __lookAhead += __pattSize;
- __tailSize -= __pattSize;
- }
- _DistanceType __remainder = __skipOffset;
- for (_RandomAccessIter __backTrack = __lookAhead - 1;
- *__backTrack == __val; --__backTrack)
- {
- if (--__remainder == 0)
- return (__lookAhead - __skipOffset); // Success
- }
- if (__remainder > __tailSize)
- return __last; // Failure
- __lookAhead += __remainder;
- __tailSize -= __remainder;
- }
- }
-
// search_n
/**
@@ -515,33 +294,6 @@
}
// find_end for forward iterators.
- template<typename _ForwardIterator1, typename _ForwardIterator2>
- _ForwardIterator1
- __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
- _ForwardIterator2 __first2, _ForwardIterator2 __last2,
- forward_iterator_tag, forward_iterator_tag)
- {
- if (__first2 == __last2)
- return __last1;
- else
- {
- _ForwardIterator1 __result = __last1;
- while (1)
- {
- _ForwardIterator1 __new_result
- = _GLIBCXX_STD_A::search(__first1, __last1, __first2, __last2);
- if (__new_result == __last1)
- return __result;
- else
- {
- __result = __new_result;
- __first1 = __new_result;
- ++__first1;
- }
- }
- }
- }
-
template<typename _ForwardIterator1, typename _ForwardIterator2,
typename _BinaryPredicate>
_ForwardIterator1
@@ -573,40 +325,6 @@
}
// find_end for bidirectional iterators (much faster).
- template<typename _BidirectionalIterator1, typename _BidirectionalIterator2>
- _BidirectionalIterator1
- __find_end(_BidirectionalIterator1 __first1,
- _BidirectionalIterator1 __last1,
- _BidirectionalIterator2 __first2,
- _BidirectionalIterator2 __last2,
- bidirectional_iterator_tag, bidirectional_iterator_tag)
- {
- // concept requirements
- __glibcxx_function_requires(_BidirectionalIteratorConcept<
- _BidirectionalIterator1>)
- __glibcxx_function_requires(_BidirectionalIteratorConcept<
- _BidirectionalIterator2>)
-
- typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1;
- typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2;
-
- _RevIterator1 __rlast1(__first1);
- _RevIterator2 __rlast2(__first2);
- _RevIterator1 __rresult = _GLIBCXX_STD_A::search(_RevIterator1(__last1),
- __rlast1,
- _RevIterator2(__last2),
- __rlast2);
-
- if (__rresult == __rlast1)
- return __last1;
- else
- {
- _BidirectionalIterator1 __result = __rresult.base();
- std::advance(__result, -std::distance(__first2, __last2));
- return __result;
- }
- }
-
template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
typename _BinaryPredicate>
_BidirectionalIterator1
@@ -684,7 +402,10 @@
return std::__find_end(__first1, __last1, __first2, __last2,
std::__iterator_category(__first1),
- std::__iterator_category(__first2));
+ std::__iterator_category(__first2),
+ __gnu_cxx::__ops::
+ iter_equal_to<_ForwardIterator1,
+ _ForwardIterator2>());
}
/**
@@ -879,6 +600,20 @@
}
#endif
+ template<typename _InputIterator, typename _OutputIterator,
+ typename _Predicate>
+ _OutputIterator
+ __remove_copy_if(_InputIterator __first, _InputIterator __last,
+ _OutputIterator __result, _Predicate __pred)
+ {
+ for (; __first != __last; ++__first)
+ if (!bool(__pred(*__first)))
+ {
+ *__result = *__first;
+ ++__result;
+ }
+ return __result;
+ }
/**
* @brief Copy a sequence, removing elements of a given value.
@@ -907,13 +642,11 @@
typename iterator_traits<_InputIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- for (; __first != __last; ++__first)
- if (!(*__first == __value))
- {
- *__result = *__first;
- ++__result;
- }
- return __result;
+ return std::__remove_copy_if(__first, __last, __result,
+ __gnu_cxx::__ops::_Adapters<_InputIterator>
+ ::bind2nd(__gnu_cxx::__ops
+ ::iter_equal_to<_InputIterator>(),
+ __value));
}
/**
@@ -945,13 +678,7 @@
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- for (; __first != __last; ++__first)
- if (!bool(__pred(*__first)))
- {
- *__result = *__first;
- ++__result;
- }
- return __result;
+ return std::__remove_copy_if(__first, __last, __result, __pred);
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
@@ -1095,6 +822,24 @@
}
#endif
+ template<typename _ForwardIterator, typename _Predicate>
+ _ForwardIterator
+ __remove_if(_ForwardIterator __first, _ForwardIterator __last,
+ _Predicate __pred)
+ {
+ __first = _GLIBCXX_STD_A::find_if(__first, __last, __pred);
+ if (__first == __last)
+ return __first;
+ _ForwardIterator __result = __first;
+ ++__first;
+ for (; __first != __last; ++__first)
+ if (!bool(__pred(*__first)))
+ {
+ *__result = _GLIBCXX_MOVE(*__first);
+ ++__result;
+ }
+ return __result;
+ }
/**
* @brief Remove elements from a sequence.
* @ingroup mutating_algorithms
@@ -1124,18 +869,11 @@
typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- __first = _GLIBCXX_STD_A::find(__first, __last, __value);
- if(__first == __last)
- return __first;
- _ForwardIterator __result = __first;
- ++__first;
- for(; __first != __last; ++__first)
- if(!(*__first == __value))
- {
- *__result = _GLIBCXX_MOVE(*__first);
- ++__result;
- }
- return __result;
+ return std::__remove_if(__first, __last,
+ __gnu_cxx::__ops::_Adapters<_ForwardIterator>
+ ::bind2nd(__gnu_cxx::__ops
+ ::iter_equal_to<_ForwardIterator>(),
+ __value));
}
/**
@@ -1167,18 +905,26 @@
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- __first = _GLIBCXX_STD_A::find_if(__first, __last, __pred);
- if(__first == __last)
- return __first;
- _ForwardIterator __result = __first;
+ return std::__remove_if(__first, __last, __pred);
+ }
+
+ template<typename _ForwardIterator, typename _BinaryPredicate>
+ _ForwardIterator
+ __unique(_ForwardIterator __first, _ForwardIterator __last,
+ _BinaryPredicate __binary_pred)
+ {
+ // Skip the beginning, if already unique.
+ __first = _GLIBCXX_STD_A::adjacent_find(__first, __last, __binary_pred);
+ if (__first == __last)
+ return __last;
+
+ // Do the real copy work.
+ _ForwardIterator __dest = __first;
++__first;
- for(; __first != __last; ++__first)
- if(!bool(__pred(*__first)))
- {
- *__result = _GLIBCXX_MOVE(*__first);
- ++__result;
- }
- return __result;
+ while (++__first != __last)
+ if (!bool(__binary_pred(*__dest, *__first)))
+ *++__dest = _GLIBCXX_MOVE(*__first);
+ return ++__dest;
}
/**
@@ -1206,18 +952,8 @@
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- // Skip the beginning, if already unique.
- __first = _GLIBCXX_STD_A::adjacent_find(__first, __last);
- if (__first == __last)
- return __last;
-
- // Do the real copy work.
- _ForwardIterator __dest = __first;
- ++__first;
- while (++__first != __last)
- if (!(*__dest == *__first))
- *++__dest = _GLIBCXX_MOVE(*__first);
- return ++__dest;
+ return __unique(__first, __last,
+ __gnu_cxx::__ops::iter_equal_to<_ForwardIterator>());
}
/**
@@ -1248,18 +984,7 @@
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- // Skip the beginning, if already unique.
- __first = _GLIBCXX_STD_A::adjacent_find(__first, __last, __binary_pred);
- if (__first == __last)
- return __last;
-
- // Do the real copy work.
- _ForwardIterator __dest = __first;
- ++__first;
- while (++__first != __last)
- if (!bool(__binary_pred(*__dest, *__first)))
- *++__dest = _GLIBCXX_MOVE(*__first);
- return ++__dest;
+ return __unique(__first, __last, __binary_pred);
}
/**
@@ -1950,26 +1675,13 @@
}
/// This is a helper function for the sort routines.
- template<typename _RandomAccessIterator>
- void
- __heap_select(_RandomAccessIterator __first,
- _RandomAccessIterator __middle,
- _RandomAccessIterator __last)
- {
- std::make_heap(__first, __middle);
- for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
- if (*__i < *__first)
- std::__pop_heap(__first, __middle, __i);
- }
-
- /// This is a helper function for the sort routines.
template<typename _RandomAccessIterator, typename _Compare>
void
__heap_select(_RandomAccessIterator __first,
_RandomAccessIterator __middle,
_RandomAccessIterator __last, _Compare __comp)
{
- std::make_heap(__first, __middle, __comp);
+ std::__make_heap(__first, __middle, __comp);
for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
if (__comp(*__i, *__first))
std::__pop_heap(__first, __middle, __i, __comp);
@@ -1977,6 +1689,48 @@
// partial_sort
+ template<typename _InputIterator, typename _RandomAccessIterator, typename _Compare>
+ _RandomAccessIterator
+ __partial_sort_copy(_InputIterator __first, _InputIterator __last,
+ _RandomAccessIterator __result_first,
+ _RandomAccessIterator __result_last,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_InputIterator>::value_type
+ _InputValueType;
+ typedef iterator_traits<_RandomAccessIterator> _RItTraits;
+ typedef typename _RItTraits::difference_type _DistanceType;
+
+ if (__result_first == __result_last)
+ return __result_last;
+ _RandomAccessIterator __result_real_last = __result_first;
+ while (__first != __last && __result_real_last != __result_last)
+ {
+ *__result_real_last = *__first;
+ ++__result_real_last;
+ ++__first;
+ }
+
+ typedef __gnu_cxx::__ops
+ ::_RebindHelper<typename _RItTraits::reference,
+ typename _RItTraits::reference> _RbHlp;
+ std::__make_heap(__result_first, __result_real_last,
+ _RbHlp::rebind(__comp));
+ while (__first != __last)
+ {
+ if (__comp(*__first, *__result_first))
+ std::__adjust_heap(__result_first, _DistanceType(0),
+ _DistanceType(__result_real_last
+ - __result_first),
+ _InputValueType(*__first),
+ _RbHlp::rebind(__comp));
+ ++__first;
+ }
+ std::__sort_heap(__result_first, __result_real_last,
+ _RbHlp::rebind(__comp));
+ return __result_real_last;
+ }
+
/**
* @brief Copy the smallest elements of a sequence.
* @ingroup sorting_algorithms
@@ -2005,8 +1759,6 @@
_InputValueType;
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_OutputValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
@@ -2018,27 +1770,11 @@
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_valid_range(__result_first, __result_last);
- if (__result_first == __result_last)
- return __result_last;
- _RandomAccessIterator __result_real_last = __result_first;
- while(__first != __last && __result_real_last != __result_last)
- {
- *__result_real_last = *__first;
- ++__result_real_last;
- ++__first;
- }
- std::make_heap(__result_first, __result_real_last);
- while (__first != __last)
- {
- if (*__first < *__result_first)
- std::__adjust_heap(__result_first, _DistanceType(0),
- _DistanceType(__result_real_last
- - __result_first),
- _InputValueType(*__first));
- ++__first;
- }
- std::sort_heap(__result_first, __result_real_last);
- return __result_real_last;
+ return std::__partial_sort_copy(__first, __last,
+ __result_first, __result_last,
+ __gnu_cxx::__ops
+ ::iter_less<_InputIterator,
+ _RandomAccessIterator>());
}
/**
@@ -2088,49 +1824,12 @@
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_valid_range(__result_first, __result_last);
- if (__result_first == __result_last)
- return __result_last;
- _RandomAccessIterator __result_real_last = __result_first;
- while(__first != __last && __result_real_last != __result_last)
- {
- *__result_real_last = *__first;
- ++__result_real_last;
- ++__first;
- }
- std::make_heap(__result_first, __result_real_last, __comp);
- while (__first != __last)
- {
- if (__comp(*__first, *__result_first))
- std::__adjust_heap(__result_first, _DistanceType(0),
- _DistanceType(__result_real_last
- - __result_first),
- _InputValueType(*__first),
- __comp);
- ++__first;
- }
- std::sort_heap(__result_first, __result_real_last, __comp);
- return __result_real_last;
+ return std::__partial_sort_copy(__first, __last,
+ __result_first, __result_last,
+ __comp);
}
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- void
- __unguarded_linear_insert(_RandomAccessIterator __last)
- {
- typename iterator_traits<_RandomAccessIterator>::value_type
- __val = _GLIBCXX_MOVE(*__last);
- _RandomAccessIterator __next = __last;
- --__next;
- while (__val < *__next)
- {
- *__last = _GLIBCXX_MOVE(*__next);
- __last = __next;
- --__next;
- }
- *__last = _GLIBCXX_MOVE(__val);
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
void
__unguarded_linear_insert(_RandomAccessIterator __last,
@@ -2150,74 +1849,46 @@
}
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- void
- __insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- if (__first == __last)
- return;
-
- for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
- {
- if (*__i < *__first)
- {
- typename iterator_traits<_RandomAccessIterator>::value_type
- __val = _GLIBCXX_MOVE(*__i);
- _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
- *__first = _GLIBCXX_MOVE(__val);
- }
- else
- std::__unguarded_linear_insert(__i);
- }
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
void
__insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
+ typedef iterator_traits<_RandomAccessIterator> _ItTraits;
+
if (__first == __last) return;
for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
{
if (__comp(*__i, *__first))
{
- typename iterator_traits<_RandomAccessIterator>::value_type
- __val = _GLIBCXX_MOVE(*__i);
+ typename _ItTraits::value_type __val = _GLIBCXX_MOVE(*__i);
_GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
*__first = _GLIBCXX_MOVE(__val);
}
else
- std::__unguarded_linear_insert(__i, __comp);
+ std::__unguarded_linear_insert(__i,
+ __gnu_cxx::__ops
+ ::_RebindHelper<typename _ItTraits::value_type&,
+ typename _ItTraits::reference>
+ ::rebind(__comp));
}
}
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- inline void
- __unguarded_insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
- for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
- std::__unguarded_linear_insert(__i);
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
inline void
__unguarded_insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
+ typedef iterator_traits<_RandomAccessIterator> _ItTraits;
for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
- std::__unguarded_linear_insert(__i, __comp);
+ std::__unguarded_linear_insert(__i,
+ __gnu_cxx::__ops
+ ::_RebindHelper<typename _ItTraits::value_type&,
+ typename _ItTraits::reference>
+ ::rebind(__comp));
}
/**
@@ -2227,21 +1898,6 @@
enum { _S_threshold = 16 };
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- void
- __final_insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- if (__last - __first > int(_S_threshold))
- {
- std::__insertion_sort(__first, __first + int(_S_threshold));
- std::__unguarded_insertion_sort(__first + int(_S_threshold), __last);
- }
- else
- std::__insertion_sort(__first, __last);
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
void
__final_insertion_sort(_RandomAccessIterator __first,
@@ -2258,31 +1914,12 @@
}
/// This is a helper function...
- template<typename _RandomAccessIterator, typename _Tp>
+ template<typename _RandomAccessIterator, typename _Compare>
_RandomAccessIterator
__unguarded_partition(_RandomAccessIterator __first,
- _RandomAccessIterator __last, const _Tp& __pivot)
- {
- while (true)
- {
- while (*__first < __pivot)
- ++__first;
- --__last;
- while (__pivot < *__last)
- --__last;
- if (!(__first < __last))
- return __first;
- std::iter_swap(__first, __last);
- ++__first;
- }
- }
-
- /// This is a helper function...
- template<typename _RandomAccessIterator, typename _Tp, typename _Compare>
- _RandomAccessIterator
- __unguarded_partition(_RandomAccessIterator __first,
_RandomAccessIterator __last,
- const _Tp& __pivot, _Compare __comp)
+ typename std::iterator_traits<_RandomAccessIterator>
+ ::reference __pivot, _Compare __comp)
{
while (true)
{
@@ -2299,18 +1936,6 @@
}
/// This is a helper function...
- template<typename _RandomAccessIterator>
- inline _RandomAccessIterator
- __unguarded_partition_pivot(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- _RandomAccessIterator __mid = __first + (__last - __first) / 2;
- std::__move_median_first(__first, __mid, (__last - 1));
- return std::__unguarded_partition(__first + 1, __last, *__first);
- }
-
-
- /// This is a helper function...
template<typename _RandomAccessIterator, typename _Compare>
inline _RandomAccessIterator
__unguarded_partition_pivot(_RandomAccessIterator __first,
@@ -2322,28 +1947,6 @@
}
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator, typename _Size>
- void
- __introsort_loop(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Size __depth_limit)
- {
- while (__last - __first > int(_S_threshold))
- {
- if (__depth_limit == 0)
- {
- _GLIBCXX_STD_A::partial_sort(__first, __last, __last);
- return;
- }
- --__depth_limit;
- _RandomAccessIterator __cut =
- std::__unguarded_partition_pivot(__first, __last);
- std::__introsort_loop(__cut, __last, __depth_limit);
- __last = __cut;
- }
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Size, typename _Compare>
void
__introsort_loop(_RandomAccessIterator __first,
@@ -2367,44 +1970,12 @@
// sort
- template<typename _RandomAccessIterator, typename _Size>
- void
- __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth,
- _RandomAccessIterator __last, _Size __depth_limit)
- {
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
- while (__last - __first > 3)
- {
- if (__depth_limit == 0)
- {
- std::__heap_select(__first, __nth + 1, __last);
-
- // Place the nth largest element in its final position.
- std::iter_swap(__first, __nth);
- return;
- }
- --__depth_limit;
- _RandomAccessIterator __cut =
- std::__unguarded_partition_pivot(__first, __last);
- if (__cut <= __nth)
- __first = __cut;
- else
- __last = __cut;
- }
- std::__insertion_sort(__first, __last);
- }
-
template<typename _RandomAccessIterator, typename _Size, typename _Compare>
void
__introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth,
_RandomAccessIterator __last, _Size __depth_limit,
_Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
while (__last - __first > 3)
{
if (__depth_limit == 0)
@@ -2452,8 +2023,6 @@
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
@@ -2462,6 +2031,17 @@
__glibcxx_requires_partitioned_lower_pred(__first, __last,
__val, __comp);
+ return std::__lower_bound(__first, __last, __val, __comp);
+ }
+
+ template<typename _ForwardIterator, typename _Tp, typename _Compare>
+ _ForwardIterator
+ __upper_bound(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val, _Compare __comp)
+ {
+ typedef typename iterator_traits<_ForwardIterator>::difference_type
+ _DistanceType;
+
_DistanceType __len = std::distance(__first, __last);
while (__len > 0)
@@ -2469,14 +2049,14 @@
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (__comp(*__middle, __val))
+ if (__comp(__val, *__middle))
+ __len = __half;
+ else
{
__first = __middle;
++__first;
__len = __len - __half - 1;
}
- else
- __len = __half;
}
return __first;
}
@@ -2497,33 +2077,18 @@
upper_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
+ typedef iterator_traits<_ForwardIterator> _ItTraits;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
+ __glibcxx_function_requires(_LessThanOpConcept<_Tp,
+ typename _ItTraits::value_type>)
__glibcxx_requires_partitioned_upper(__first, __last, __val);
- _DistanceType __len = std::distance(__first, __last);
-
- while (__len > 0)
- {
- _DistanceType __half = __len >> 1;
- _ForwardIterator __middle = __first;
- std::advance(__middle, __half);
- if (__val < *__middle)
- __len = __half;
- else
- {
- __first = __middle;
- ++__first;
- __len = __len - __half - 1;
- }
- }
- return __first;
+ return std::__upper_bound(__first, __last, __val,
+ __gnu_cxx::__ops
+ ::less<const _Tp&,
+ typename _ItTraits::reference>());
}
/**
@@ -2558,6 +2123,19 @@
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
+ return std::__upper_bound(__first, __last, __val, __comp);
+ }
+
+ template<typename _ForwardIterator, typename _Tp,
+ typename _CompareItTp, typename _CompareTpIt>
+ pair<_ForwardIterator, _ForwardIterator>
+ __equal_range(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val,
+ _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it)
+ {
+ typedef typename iterator_traits<_ForwardIterator>::difference_type
+ _DistanceType;
+
_DistanceType __len = std::distance(__first, __last);
while (__len > 0)
@@ -2565,16 +2143,25 @@
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (__comp(__val, *__middle))
- __len = __half;
- else
+ if (__comp_it_val(*__middle, __val))
{
__first = __middle;
++__first;
__len = __len - __half - 1;
}
+ else if (__comp_val_it(__val, *__middle))
+ __len = __half;
+ else
+ {
+ _ForwardIterator __left
+ = std::__lower_bound(__first, __middle, __val, __comp_it_val);
+ std::advance(__first, __len);
+ _ForwardIterator __right
+ = std::__upper_bound(++__middle, __first, __val, __comp_val_it);
+ return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
+ }
}
- return __first;
+ return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
}
/**
@@ -2599,44 +2186,24 @@
equal_range(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
+ typedef iterator_traits<_ForwardIterator> _ItTraits;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType, _Tp>)
- __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename _ItTraits::value_type, _Tp>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ _Tp, typename _ItTraits::value_type>)
__glibcxx_requires_partitioned_lower(__first, __last, __val);
__glibcxx_requires_partitioned_upper(__first, __last, __val);
- _DistanceType __len = std::distance(__first, __last);
-
- while (__len > 0)
- {
- _DistanceType __half = __len >> 1;
- _ForwardIterator __middle = __first;
- std::advance(__middle, __half);
- if (*__middle < __val)
- {
- __first = __middle;
- ++__first;
- __len = __len - __half - 1;
- }
- else if (__val < *__middle)
- __len = __half;
- else
- {
- _ForwardIterator __left = std::lower_bound(__first, __middle,
- __val);
- std::advance(__first, __len);
- _ForwardIterator __right = std::upper_bound(++__middle, __first,
- __val);
- return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
- }
- }
- return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
+ return std::__equal_range(__first, __last, __val,
+ __gnu_cxx::__ops
+ ::less<typename _ItTraits::reference,
+ const _Tp&>(),
+ __gnu_cxx::__ops
+ ::less<const _Tp&,
+ typename _ItTraits::reference>());
}
/**
@@ -2677,32 +2244,7 @@
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
- _DistanceType __len = std::distance(__first, __last);
-
- while (__len > 0)
- {
- _DistanceType __half = __len >> 1;
- _ForwardIterator __middle = __first;
- std::advance(__middle, __half);
- if (__comp(*__middle, __val))
- {
- __first = __middle;
- ++__first;
- __len = __len - __half - 1;
- }
- else if (__comp(__val, *__middle))
- __len = __half;
- else
- {
- _ForwardIterator __left = std::lower_bound(__first, __middle,
- __val, __comp);
- std::advance(__first, __len);
- _ForwardIterator __right = std::upper_bound(++__middle, __first,
- __val, __comp);
- return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
- }
- }
- return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
+ return std::__equal_range(__first, __last, __val, __comp, __comp);
}
/**
@@ -2722,16 +2264,20 @@
binary_search(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
+ typedef iterator_traits<_ForwardIterator> _ItTraits;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ _Tp, typename _ItTraits::value_type>)
__glibcxx_requires_partitioned_lower(__first, __last, __val);
__glibcxx_requires_partitioned_upper(__first, __last, __val);
- _ForwardIterator __i = std::lower_bound(__first, __last, __val);
+ _ForwardIterator __i
+ = std::__lower_bound(__first, __last, __val,
+ __gnu_cxx::__ops
+ ::less<typename _ItTraits::reference,
+ const _Tp&>());
return __i != __last && !(__val < *__i);
}
@@ -2767,7 +2313,7 @@
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
- _ForwardIterator __i = std::lower_bound(__first, __last, __val, __comp);
+ _ForwardIterator __i = std::__lower_bound(__first, __last, __val, __comp);
return __i != __last && !bool(__comp(__val, *__i));
}
@@ -2775,32 +2321,6 @@
/// This is a helper function for the __merge_adaptive routines.
template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator>
- void
- __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
- _InputIterator2 __first2, _InputIterator2 __last2,
- _OutputIterator __result)
- {
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (*__first2 < *__first1)
- {
- *__result = _GLIBCXX_MOVE(*__first2);
- ++__first2;
- }
- else
- {
- *__result = _GLIBCXX_MOVE(*__first1);
- ++__first1;
- }
- ++__result;
- }
- if (__first1 != __last1)
- _GLIBCXX_MOVE3(__first1, __last1, __result);
- }
-
- /// This is a helper function for the __merge_adaptive routines.
- template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
void
__move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
@@ -2827,48 +2347,6 @@
/// This is a helper function for the __merge_adaptive routines.
template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
- typename _BidirectionalIterator3>
- void
- __move_merge_adaptive_backward(_BidirectionalIterator1 __first1,
- _BidirectionalIterator1 __last1,
- _BidirectionalIterator2 __first2,
- _BidirectionalIterator2 __last2,
- _BidirectionalIterator3 __result)
- {
- if (__first1 == __last1)
- {
- _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result);
- return;
- }
- else if (__first2 == __last2)
- return;
-
- --__last1;
- --__last2;
- while (true)
- {
- if (*__last2 < *__last1)
- {
- *--__result = _GLIBCXX_MOVE(*__last1);
- if (__first1 == __last1)
- {
- _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result);
- return;
- }
- --__last1;
- }
- else
- {
- *--__result = _GLIBCXX_MOVE(*__last2);
- if (__first2 == __last2)
- return;
- --__last2;
- }
- }
- }
-
- /// This is a helper function for the __merge_adaptive routines.
- template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
typename _BidirectionalIterator3, typename _Compare>
void
__move_merge_adaptive_backward(_BidirectionalIterator1 __first1,
@@ -2953,62 +2431,6 @@
}
/// This is a helper function for the merge routines.
- template<typename _BidirectionalIterator, typename _Distance,
- typename _Pointer>
- void
- __merge_adaptive(_BidirectionalIterator __first,
- _BidirectionalIterator __middle,
- _BidirectionalIterator __last,
- _Distance __len1, _Distance __len2,
- _Pointer __buffer, _Distance __buffer_size)
- {
- if (__len1 <= __len2 && __len1 <= __buffer_size)
- {
- _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
- std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
- __first);
- }
- else if (__len2 <= __buffer_size)
- {
- _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
- std::__move_merge_adaptive_backward(__first, __middle, __buffer,
- __buffer_end, __last);
- }
- else
- {
- _BidirectionalIterator __first_cut = __first;
- _BidirectionalIterator __second_cut = __middle;
- _Distance __len11 = 0;
- _Distance __len22 = 0;
- if (__len1 > __len2)
- {
- __len11 = __len1 / 2;
- std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last,
- *__first_cut);
- __len22 = std::distance(__middle, __second_cut);
- }
- else
- {
- __len22 = __len2 / 2;
- std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle,
- *__second_cut);
- __len11 = std::distance(__first, __first_cut);
- }
- _BidirectionalIterator __new_middle =
- std::__rotate_adaptive(__first_cut, __middle, __second_cut,
- __len1 - __len11, __len22, __buffer,
- __buffer_size);
- std::__merge_adaptive(__first, __first_cut, __new_middle, __len11,
- __len22, __buffer, __buffer_size);
- std::__merge_adaptive(__new_middle, __second_cut, __last,
- __len1 - __len11,
- __len2 - __len22, __buffer, __buffer_size);
- }
- }
-
- /// This is a helper function for the merge routines.
template<typename _BidirectionalIterator, typename _Distance,
typename _Pointer, typename _Compare>
void
@@ -3019,17 +2441,25 @@
_Pointer __buffer, _Distance __buffer_size,
_Compare __comp)
{
+ typedef std::iterator_traits<_BidirectionalIterator> _ItTraits;
+ typedef std::iterator_traits<_Pointer> _PtrTraits;
if (__len1 <= __len2 && __len1 <= __buffer_size)
{
_Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
- std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
- __first, __comp);
+ std::__move_merge_adaptive(
+ __buffer, __buffer_end, __middle, __last, __first,
+ __gnu_cxx::__ops::_RebindHelper<typename _ItTraits::reference,
+ typename _PtrTraits::reference>
+ ::rebind(__comp));
}
else if (__len2 <= __buffer_size)
{
_Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
- std::__move_merge_adaptive_backward(__first, __middle, __buffer,
- __buffer_end, __last, __comp);
+ std::__move_merge_adaptive_backward(
+ __first, __middle, __buffer, __buffer_end, __last,
+ __gnu_cxx::__ops::_RebindHelper<typename _PtrTraits::reference,
+ typename _ItTraits::reference>
+ ::rebind(__comp));
}
else
{
@@ -3041,16 +2471,22 @@
{
__len11 = __len1 / 2;
std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last, *__first_cut,
- __comp);
+ __second_cut = std::__lower_bound(__middle, __last, *__first_cut,
+ __gnu_cxx::__ops
+ ::_RebindHelper<typename _ItTraits::reference,
+ typename _ItTraits::value_type const&>
+ ::rebind(__comp));
__len22 = std::distance(__middle, __second_cut);
}
else
{
__len22 = __len2 / 2;
std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle, *__second_cut,
- __comp);
+ __first_cut = std::__upper_bound(__first, __middle, *__second_cut,
+ __gnu_cxx::__ops
+ ::_RebindHelper<typename _ItTraits::value_type const&,
+ typename _ItTraits::reference>
+ ::rebind(__comp));
__len11 = std::distance(__first, __first_cut);
}
_BidirectionalIterator __new_middle =
@@ -3067,49 +2503,6 @@
}
/// This is a helper function for the merge routines.
- template<typename _BidirectionalIterator, typename _Distance>
- void
- __merge_without_buffer(_BidirectionalIterator __first,
- _BidirectionalIterator __middle,
- _BidirectionalIterator __last,
- _Distance __len1, _Distance __len2)
- {
- if (__len1 == 0 || __len2 == 0)
- return;
- if (__len1 + __len2 == 2)
- {
- if (*__middle < *__first)
- std::iter_swap(__first, __middle);
- return;
- }
- _BidirectionalIterator __first_cut = __first;
- _BidirectionalIterator __second_cut = __middle;
- _Distance __len11 = 0;
- _Distance __len22 = 0;
- if (__len1 > __len2)
- {
- __len11 = __len1 / 2;
- std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last, *__first_cut);
- __len22 = std::distance(__middle, __second_cut);
- }
- else
- {
- __len22 = __len2 / 2;
- std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle, *__second_cut);
- __len11 = std::distance(__first, __first_cut);
- }
- std::rotate(__first_cut, __middle, __second_cut);
- _BidirectionalIterator __new_middle = __first_cut;
- std::advance(__new_middle, std::distance(__middle, __second_cut));
- std::__merge_without_buffer(__first, __first_cut, __new_middle,
- __len11, __len22);
- std::__merge_without_buffer(__new_middle, __second_cut, __last,
- __len1 - __len11, __len2 - __len22);
- }
-
- /// This is a helper function for the merge routines.
template<typename _BidirectionalIterator, typename _Distance,
typename _Compare>
void
@@ -3119,6 +2512,7 @@
_Distance __len1, _Distance __len2,
_Compare __comp)
{
+ typedef std::iterator_traits<_BidirectionalIterator> _ItTraits;
if (__len1 == 0 || __len2 == 0)
return;
if (__len1 + __len2 == 2)
@@ -3135,16 +2529,22 @@
{
__len11 = __len1 / 2;
std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last, *__first_cut,
- __comp);
+ __second_cut = std::__lower_bound(__middle, __last, *__first_cut,
+ __gnu_cxx::__ops
+ ::_RebindHelper<typename _ItTraits::reference,
+ typename _ItTraits::value_type const&>
+ ::rebind(__comp));
__len22 = std::distance(__middle, __second_cut);
}
else
{
__len22 = __len2 / 2;
std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle, *__second_cut,
- __comp);
+ __first_cut = std::__upper_bound(__first, __middle, *__second_cut,
+ __gnu_cxx::__ops
+ ::_RebindHelper<typename _ItTraits::value_type const&,
+ typename _ItTraits::reference>
+ ::rebind(__comp));
__len11 = std::distance(__first, __first_cut);
}
std::rotate(__first_cut, __middle, __second_cut);
@@ -3156,6 +2556,35 @@
__len1 - __len11, __len2 - __len22, __comp);
}
+ template<typename _BidirectionalIterator, typename _Compare>
+ void
+ __inplace_merge(_BidirectionalIterator __first,
+ _BidirectionalIterator __middle,
+ _BidirectionalIterator __last,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_BidirectionalIterator>::value_type
+ _ValueType;
+ typedef typename iterator_traits<_BidirectionalIterator>::difference_type
+ _DistanceType;
+
+ if (__first == __middle || __middle == __last)
+ return;
+
+ const _DistanceType __len1 = std::distance(__first, __middle);
+ const _DistanceType __len2 = std::distance(__middle, __last);
+
+ _Temporary_buffer<_BidirectionalIterator, _ValueType> __buf(__first,
+ __last);
+ if (__buf.begin() == 0)
+ std::__merge_without_buffer(__first, __middle, __last, __len1,
+ __len2, __comp);
+ else
+ std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
+ __buf.begin(), _DistanceType(__buf.size()),
+ __comp);
+ }
+
/**
* @brief Merges two sorted ranges in place.
* @ingroup sorting_algorithms
@@ -3192,19 +2621,9 @@
__glibcxx_requires_sorted(__first, __middle);
__glibcxx_requires_sorted(__middle, __last);
- if (__first == __middle || __middle == __last)
- return;
-
- _DistanceType __len1 = std::distance(__first, __middle);
- _DistanceType __len2 = std::distance(__middle, __last);
-
- _Temporary_buffer<_BidirectionalIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__merge_without_buffer(__first, __middle, __last, __len1, __len2);
- else
- std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
- __buf.begin(), _DistanceType(__buf.size()));
+ std::__inplace_merge(__first, __middle, __last,
+ __gnu_cxx::__ops
+ ::iter_less<_BidirectionalIterator>());
}
/**
@@ -3249,57 +2668,16 @@
__glibcxx_requires_sorted_pred(__first, __middle, __comp);
__glibcxx_requires_sorted_pred(__middle, __last, __comp);
- if (__first == __middle || __middle == __last)
- return;
-
- const _DistanceType __len1 = std::distance(__first, __middle);
- const _DistanceType __len2 = std::distance(__middle, __last);
-
- _Temporary_buffer<_BidirectionalIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__merge_without_buffer(__first, __middle, __last, __len1,
- __len2, __comp);
- else
- std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
- __buf.begin(), _DistanceType(__buf.size()),
- __comp);
+ std::__inplace_merge(__first, __middle, __last, __comp);
}
/// This is a helper function for the __merge_sort_loop routines.
- template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator>
+ template<typename _InputIterator, typename _OutputIterator,
+ typename _Compare>
_OutputIterator
- __move_merge(_InputIterator1 __first1, _InputIterator1 __last1,
- _InputIterator2 __first2, _InputIterator2 __last2,
- _OutputIterator __result)
- {
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (*__first2 < *__first1)
- {
- *__result = _GLIBCXX_MOVE(*__first2);
- ++__first2;
- }
- else
- {
- *__result = _GLIBCXX_MOVE(*__first1);
- ++__first1;
- }
- ++__result;
- }
- return _GLIBCXX_MOVE3(__first2, __last2,
- _GLIBCXX_MOVE3(__first1, __last1,
- __result));
- }
-
- /// This is a helper function for the __merge_sort_loop routines.
- template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator, typename _Compare>
- _OutputIterator
- __move_merge(_InputIterator1 __first1, _InputIterator1 __last1,
- _InputIterator2 __first2, _InputIterator2 __last2,
+ __move_merge(_InputIterator __first1, _InputIterator __last1,
+ _InputIterator __first2, _InputIterator __last2,
_OutputIterator __result, _Compare __comp)
{
while (__first1 != __last1 && __first2 != __last2)
@@ -3322,29 +2700,6 @@
}
template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
- typename _Distance>
- void
- __merge_sort_loop(_RandomAccessIterator1 __first,
- _RandomAccessIterator1 __last,
- _RandomAccessIterator2 __result,
- _Distance __step_size)
- {
- const _Distance __two_step = 2 * __step_size;
-
- while (__last - __first >= __two_step)
- {
- __result = std::__move_merge(__first, __first + __step_size,
- __first + __step_size,
- __first + __two_step, __result);
- __first += __two_step;
- }
-
- __step_size = std::min(_Distance(__last - __first), __step_size);
- std::__move_merge(__first, __first + __step_size,
- __first + __step_size, __last, __result);
- }
-
- template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
typename _Distance, typename _Compare>
void
__merge_sort_loop(_RandomAccessIterator1 __first,
@@ -3364,24 +2719,10 @@
}
__step_size = std::min(_Distance(__last - __first), __step_size);
- std::__move_merge(__first,__first + __step_size,
+ std::__move_merge(__first, __first + __step_size,
__first + __step_size, __last, __result, __comp);
}
- template<typename _RandomAccessIterator, typename _Distance>
- void
- __chunk_insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Distance __chunk_size)
- {
- while (__last - __first >= __chunk_size)
- {
- std::__insertion_sort(__first, __first + __chunk_size);
- __first += __chunk_size;
- }
- std::__insertion_sort(__first, __last);
- }
-
template<typename _RandomAccessIterator, typename _Distance,
typename _Compare>
void
@@ -3399,30 +2740,6 @@
enum { _S_chunk_size = 7 };
- template<typename _RandomAccessIterator, typename _Pointer>
- void
- __merge_sort_with_buffer(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Pointer __buffer)
- {
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _Distance;
-
- const _Distance __len = __last - __first;
- const _Pointer __buffer_last = __buffer + __len;
-
- _Distance __step_size = _S_chunk_size;
- std::__chunk_insertion_sort(__first, __last, __step_size);
-
- while (__step_size < __len)
- {
- std::__merge_sort_loop(__first, __last, __buffer, __step_size);
- __step_size *= 2;
- std::__merge_sort_loop(__buffer, __buffer_last, __first, __step_size);
- __step_size *= 2;
- }
- }
-
template<typename _RandomAccessIterator, typename _Pointer, typename _Compare>
void
__merge_sort_with_buffer(_RandomAccessIterator __first,
@@ -3450,33 +2767,6 @@
}
template<typename _RandomAccessIterator, typename _Pointer,
- typename _Distance>
- void
- __stable_sort_adaptive(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Pointer __buffer, _Distance __buffer_size)
- {
- const _Distance __len = (__last - __first + 1) / 2;
- const _RandomAccessIterator __middle = __first + __len;
- if (__len > __buffer_size)
- {
- std::__stable_sort_adaptive(__first, __middle,
- __buffer, __buffer_size);
- std::__stable_sort_adaptive(__middle, __last,
- __buffer, __buffer_size);
- }
- else
- {
- std::__merge_sort_with_buffer(__first, __middle, __buffer);
- std::__merge_sort_with_buffer(__middle, __last, __buffer);
- }
- std::__merge_adaptive(__first, __middle, __last,
- _Distance(__middle - __first),
- _Distance(__last - __middle),
- __buffer, __buffer_size);
- }
-
- template<typename _RandomAccessIterator, typename _Pointer,
typename _Distance, typename _Compare>
void
__stable_sort_adaptive(_RandomAccessIterator __first,
@@ -3506,25 +2796,6 @@
}
/// This is a helper function for the stable sorting routines.
- template<typename _RandomAccessIterator>
- void
- __inplace_stable_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- if (__last - __first < 15)
- {
- std::__insertion_sort(__first, __last);
- return;
- }
- _RandomAccessIterator __middle = __first + (__last - __first) / 2;
- std::__inplace_stable_sort(__first, __middle);
- std::__inplace_stable_sort(__middle, __last);
- std::__merge_without_buffer(__first, __middle, __last,
- __middle - __first,
- __last - __middle);
- }
-
- /// This is a helper function for the stable sorting routines.
template<typename _RandomAccessIterator, typename _Compare>
void
__inplace_stable_sort(_RandomAccessIterator __first,
@@ -4462,8 +3733,11 @@
__glibcxx_function_requires(_EqualOpConcept<
typename iterator_traits<_InputIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__find(__first, __last, __val,
- std::__iterator_category(__first));
+ return std::__find_if(__first, __last,
+ __gnu_cxx::__ops::_Adapters<_InputIterator>
+ ::bind2nd(__gnu_cxx::__ops::
+ iter_equal_to<_InputIterator>(), __val),
+ std::__iterator_category(__first));
}
/**
@@ -4871,6 +4145,8 @@
if (__count == 1)
return _GLIBCXX_STD_A::find(__first, __last, __val);
return std::__search_n(__first, __last, __count, __val,
+ __gnu_cxx::__ops
+ ::iter_equal_to_val<_ForwardIterator, _Tp>(),
std::__iterator_category(__first));
}
@@ -5321,8 +4597,10 @@
__glibcxx_requires_valid_range(__first, __middle);
__glibcxx_requires_valid_range(__middle, __last);
- std::__heap_select(__first, __middle, __last);
- std::sort_heap(__first, __middle);
+ std::__heap_select(__first, __middle, __last,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
+ std::__sort_heap(__first, __middle,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
}
/**
@@ -5363,7 +4641,7 @@
__glibcxx_requires_valid_range(__middle, __last);
std::__heap_select(__first, __middle, __last, __comp);
- std::sort_heap(__first, __middle, __comp);
+ std::__sort_heap(__first, __middle, __comp);
}
/**
@@ -5400,7 +4678,8 @@
return;
std::__introselect(__first, __nth, __last,
- std::__lg(__last - __first) * 2);
+ std::__lg(__last - __first) * 2,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
}
/**
@@ -5444,6 +4723,19 @@
}
+ template<typename _RandomAccessIterator, typename _Compare>
+ inline void
+ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
+ {
+ if (__first != __last)
+ {
+ std::__introsort_loop(__first, __last,
+ std::__lg(__last - __first) * 2, __comp);
+ std::__final_insertion_sort(__first, __last, __comp);
+ }
+ }
+
/**
* @brief Sort the elements of a sequence.
* @ingroup sorting_algorithms
@@ -5471,12 +4763,8 @@
__glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first != __last)
- {
- std::__introsort_loop(__first, __last,
- std::__lg(__last - __first) * 2);
- std::__final_insertion_sort(__first, __last);
- }
+ __sort(__first, __last,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
}
/**
@@ -5509,12 +4797,7 @@
_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first != __last)
- {
- std::__introsort_loop(__first, __last,
- std::__lg(__last - __first) * 2, __comp);
- std::__final_insertion_sort(__first, __last, __comp);
- }
+ __sort(__first, __last, __comp);
}
/**
@@ -5642,7 +4925,25 @@
__result));
}
+ template<typename _RandomAccessIterator, typename _Compare>
+ inline void
+ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_RandomAccessIterator>::value_type
+ _ValueType;
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+ _DistanceType;
+ _Temporary_buffer<_RandomAccessIterator, _ValueType> __buf(__first,
+ __last);
+ if (__buf.begin() == 0)
+ std::__inplace_stable_sort(__first, __last, __comp);
+ else
+ std::__stable_sort_adaptive(__first, __last, __buf.begin(),
+ _DistanceType(__buf.size()), __comp);
+ }
+
/**
* @brief Sort the elements of a sequence, preserving the relative order
* of equivalent elements.
@@ -5666,8 +4967,6 @@
{
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
@@ -5675,13 +4974,8 @@
__glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
- _Temporary_buffer<_RandomAccessIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__inplace_stable_sort(__first, __last);
- else
- std::__stable_sort_adaptive(__first, __last, __buf.begin(),
- _DistanceType(__buf.size()));
+ std::__stable_sort(__first, __last,
+ __gnu_cxx::__ops::iter_less<_RandomAccessIterator>());
}
/**
@@ -5709,8 +5003,6 @@
{
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
@@ -5720,16 +5012,43 @@
_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
- _Temporary_buffer<_RandomAccessIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__inplace_stable_sort(__first, __last, __comp);
- else
- std::__stable_sort_adaptive(__first, __last, __buf.begin(),
- _DistanceType(__buf.size()), __comp);
+ std::__stable_sort(__first, __last, __comp);
}
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare12, typename _Compare21>
+ _OutputIterator
+ __set_union(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result,
+ _Compare12 __comp12, _Compare21 __comp21)
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ {
+ if (__comp12(*__first1, *__first2))
+ {
+ *__result = *__first1;
+ ++__first1;
+ }
+ else if (__comp21(*__first2, *__first1))
+ {
+ *__result = *__first2;
+ ++__first2;
+ }
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__first2;
+ }
+ ++__result;
+ }
+ return std::copy(__first2, __last2, std::copy(__first1, __last1,
+ __result));
+ }
+
/**
* @brief Return the union of two sorted ranges.
* @ingroup set_algorithms
@@ -5772,28 +5091,10 @@
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (*__first1 < *__first2)
- {
- *__result = *__first1;
- ++__first1;
- }
- else if (*__first2 < *__first1)
- {
- *__result = *__first2;
- ++__first2;
- }
- else
- {
- *__result = *__first1;
- ++__first1;
- ++__first2;
- }
- ++__result;
- }
- return std::copy(__first2, __last2, std::copy(__first1, __last1,
- __result));
+ return std::__set_union(
+ __first1, __last1, __first2, __last2, __result,
+ __gnu_cxx::__ops::iter_less<_InputIterator1, _InputIterator2>(),
+ __gnu_cxx::__ops::iter_less<_InputIterator2, _InputIterator1>());
}
/**
@@ -5841,28 +5142,32 @@
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
+ return std::__set_union(__first1, __last1, __first2, __last2, __result,
+ __comp, __comp);
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare12, typename _Compare21>
+ _OutputIterator
+ __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result,
+ _Compare12 __comp12, _Compare21 __comp21)
+ {
while (__first1 != __last1 && __first2 != __last2)
- {
- if (__comp(*__first1, *__first2))
- {
- *__result = *__first1;
- ++__first1;
- }
- else if (__comp(*__first2, *__first1))
- {
- *__result = *__first2;
- ++__first2;
- }
- else
- {
- *__result = *__first1;
- ++__first1;
- ++__first2;
- }
- ++__result;
- }
- return std::copy(__first2, __last2, std::copy(__first1, __last1,
- __result));
+ if (__comp12(*__first1, *__first2))
+ ++__first1;
+ else if (__comp21(*__first2, *__first1))
+ ++__first2;
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__first2;
+ ++__result;
+ }
+ return __result;
}
/**
@@ -5904,19 +5209,10 @@
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first1 < *__first2)
- ++__first1;
- else if (*__first2 < *__first1)
- ++__first2;
- else
- {
- *__result = *__first1;
- ++__first1;
- ++__first2;
- ++__result;
- }
- return __result;
+ return std::__set_intersection(
+ __first1, __last1, __first2, __last2, __result,
+ __gnu_cxx::__ops::iter_less<_InputIterator1, _InputIterator2>(),
+ __gnu_cxx::__ops::iter_less<_InputIterator2, _InputIterator1>());
}
/**
@@ -5963,19 +5259,34 @@
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
+ return std::__set_intersection(__first1, __last1, __first2, __last2,
+ __result, __comp, __comp);
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare12, typename _Compare21>
+ _OutputIterator
+ __set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result,
+ _Compare12 __comp12, _Compare21 __comp21)
+ {
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first1, *__first2))
- ++__first1;
- else if (__comp(*__first2, *__first1))
+ if (__comp12(*__first1, *__first2))
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__result;
+ }
+ else if (__comp21(*__first2, *__first1))
++__first2;
else
{
- *__result = *__first1;
++__first1;
++__first2;
- ++__result;
}
- return __result;
+ return std::copy(__first1, __last1, __result);
}
/**
@@ -6019,21 +5330,10 @@
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first1 < *__first2)
- {
- *__result = *__first1;
- ++__first1;
- ++__result;
- }
- else if (*__first2 < *__first1)
- ++__first2;
- else
- {
- ++__first1;
- ++__first2;
- }
- return std::copy(__first1, __last1, __result);
+ return std::__set_difference(
+ __first1, __last1, __first2, __last2, __result,
+ __gnu_cxx::__ops::iter_less<_InputIterator1, _InputIterator2>(),
+ __gnu_cxx::__ops::iter_less<_InputIterator2, _InputIterator1>());
}
/**
@@ -6082,21 +5382,39 @@
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
+ return std::__set_difference(__first1, __last1, __first2, __last2,
+ __result, __comp, __comp);
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare12, typename _Compare21>
+ _OutputIterator
+ __set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result,
+ _Compare12 __comp12, _Compare21 __comp21)
+ {
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first1, *__first2))
+ if (__comp12(*__first1, *__first2))
{
*__result = *__first1;
++__first1;
++__result;
}
- else if (__comp(*__first2, *__first1))
- ++__first2;
+ else if (__comp21(*__first2, *__first1))
+ {
+ *__result = *__first2;
+ ++__first2;
+ ++__result;
+ }
else
{
++__first1;
++__first2;
}
- return std::copy(__first1, __last1, __result);
+ return std::copy(__first2, __last2,
+ std::copy(__first1, __last1, __result));
}
/**
@@ -6140,26 +5458,10 @@
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first1 < *__first2)
- {
- *__result = *__first1;
- ++__first1;
- ++__result;
- }
- else if (*__first2 < *__first1)
- {
- *__result = *__first2;
- ++__first2;
- ++__result;
- }
- else
- {
- ++__first1;
- ++__first2;
- }
- return std::copy(__first2, __last2, std::copy(__first1,
- __last1, __result));
+ return std::__set_symmetric_difference(
+ __first1, __last1, __first2, __last2, __result,
+ __gnu_cxx::__ops::iter_less<_InputIterator1, _InputIterator2>(),
+ __gnu_cxx::__ops::iter_less<_InputIterator2, _InputIterator1>());
}
/**
@@ -6209,28 +5511,24 @@
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
- while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first1, *__first2))
- {
- *__result = *__first1;
- ++__first1;
- ++__result;
- }
- else if (__comp(*__first2, *__first1))
- {
- *__result = *__first2;
- ++__first2;
- ++__result;
- }
- else
- {
- ++__first1;
- ++__first2;
- }
- return std::copy(__first2, __last2,
- std::copy(__first1, __last1, __result));
+ return std::__set_symmetric_difference(__first1, __last1,
+ __first2, __last2, __result,
+ __comp, __comp);
}
+ template<typename _ForwardIterator, typename _Compare>
+ _ForwardIterator
+ __min_element(_ForwardIterator __first, _ForwardIterator __last,
+ _Compare __comp)
+ {
+ if (__first == __last)
+ return __first;
+ _ForwardIterator __result = __first;
+ while (++__first != __last)
+ if (__comp(*__first, *__result))
+ __result = __first;
+ return __result;
+ }
/**
* @brief Return the minimum element in a range.
@@ -6249,13 +5547,8 @@
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __first;
- _ForwardIterator __result = __first;
- while (++__first != __last)
- if (*__first < *__result)
- __result = __first;
- return __result;
+ return std::__min_element(__first, __last,
+ __gnu_cxx::__ops::iter_less<_ForwardIterator>());
}
/**
@@ -6279,15 +5572,21 @@
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __first;
+ return std::__min_element(__first, __last, __comp);
+ }
+
+ template<typename _ForwardIterator, typename _Compare>
+ _ForwardIterator
+ __max_element(_ForwardIterator __first, _ForwardIterator __last,
+ _Compare __comp)
+ {
+ if (__first == __last) return __first;
_ForwardIterator __result = __first;
while (++__first != __last)
- if (__comp(*__first, *__result))
+ if (__comp(*__result, *__first))
__result = __first;
return __result;
}
-
/**
* @brief Return the maximum element in a range.
* @ingroup sorting_algorithms
@@ -6305,13 +5604,8 @@
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __first;
- _ForwardIterator __result = __first;
- while (++__first != __last)
- if (*__result < *__first)
- __result = __first;
- return __result;
+ return std::__max_element(__first, __last,
+ __gnu_cxx::__ops::iter_less<_ForwardIterator>());
}
/**
@@ -6335,12 +5629,7 @@
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last) return __first;
- _ForwardIterator __result = __first;
- while (++__first != __last)
- if (__comp(*__result, *__first))
- __result = __first;
- return __result;
+ return std::__max_element(__first, __last, __comp);
}
_GLIBCXX_END_NAMESPACE_ALGO
Index: include/Makefile.am
===================================================================
--- include/Makefile.am (revision 188314)
+++ include/Makefile.am (working copy)
@@ -138,6 +138,7 @@
${bits_srcdir}/shared_ptr_base.h \
${bits_srcdir}/slice_array.h \
${bits_srcdir}/sstream.tcc \
+ ${bits_srcdir}/predefined_ops.h \
${bits_srcdir}/stl_algo.h \
${bits_srcdir}/stl_algobase.h \
${bits_srcdir}/stl_bvector.h \
Index: testsuite/util/testsuite_counter_type.h
===================================================================
--- testsuite/util/testsuite_counter_type.h (revision 0)
+++ testsuite/util/testsuite_counter_type.h (revision 0)
@@ -0,0 +1,332 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2012 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/>.
+//
+
+#ifndef _TESTSUITE_COUNTER_TYPE_H
+#define _TESTSUITE_COUNTER_TYPE_H 1
+
+#include <iterator>
+
+namespace __gnu_test
+{
+ // Type counting how many constructors are invoked. Used mainly to check that
+ // in algo implementation we do not copy values too often even when operators
+ // are taking type by value.
+ struct counter_type
+ {
+ // Constructor counters:
+ static int default_count;
+ static int specialize_count;
+ static int copy_count;
+ static int copy_assign_count;
+ static int less_compare_count;
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ static int move_count;
+ static int move_assign_count;
+#endif
+
+ int val;
+
+ counter_type() : val(0)
+ {
+ ++default_count;
+ }
+
+ counter_type(int inval) : val(inval)
+ {
+ ++specialize_count;
+ }
+
+ counter_type(const counter_type& in) : val(in.val)
+ {
+ ++copy_count;
+ }
+
+ counter_type&
+ operator=(const counter_type& in)
+ {
+ val = in.val;
+ ++copy_assign_count;
+ return *this;
+ }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ counter_type(counter_type&& in) noexcept
+ {
+ val = in.val;
+ ++move_count;
+ }
+
+ counter_type&
+ operator=(counter_type&& rhs)
+ {
+ val = rhs.val;
+ ++move_assign_count;
+ return *this;
+ }
+#endif
+
+ static void
+ reset()
+ {
+ default_count = 0;
+ specialize_count = 0;
+ copy_count = 0;
+ copy_assign_count = 0;
+ less_compare_count = 0;
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ move_count = 0;
+ move_assign_count = 0;
+#endif
+ }
+
+ bool operator==(counter_type rhs) const
+ { return val == rhs.val; }
+ };
+
+ int counter_type::default_count = 0;
+ int counter_type::specialize_count = 0;
+ int counter_type::copy_count = 0;
+ int counter_type::copy_assign_count = 0;
+ int counter_type::less_compare_count = 0;
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ int counter_type::move_count = 0;
+ int counter_type::move_assign_count = 0;
+#endif
+
+#ifdef LESS_OPERATOR_TAKES_COPY
+ bool operator<(counter_type lhs, counter_type rhs)
+ {
+ ++counter_type::less_compare_count;
+ return lhs.val < rhs.val;
+ }
+#else
+ bool operator<(const counter_type& lhs, const counter_type& rhs)
+ {
+ ++counter_type::less_compare_count;
+ return lhs.val < rhs.val;
+ }
+#endif
+
+ template<typename _Iterator>
+ class copy_iterator
+ {
+ protected:
+ _Iterator _M_current;
+
+ typedef std::iterator_traits<_Iterator> __traits_type;
+
+ public:
+ typedef _Iterator iterator_type;
+ typedef typename __traits_type::iterator_category iterator_category;
+ typedef typename __traits_type::value_type value_type;
+ typedef typename __traits_type::difference_type difference_type;
+ // NB: DR 680.
+ typedef _Iterator pointer;
+ typedef value_type reference;
+
+ copy_iterator()
+ : _M_current() { }
+
+ explicit
+ copy_iterator(iterator_type __i)
+ : _M_current(__i) { }
+
+ template<typename _Iter>
+ copy_iterator(const copy_iterator<_Iter>& __i)
+ : _M_current(__i.base()) { }
+
+ iterator_type
+ base() const
+ { return _M_current; }
+
+ reference
+ operator*() const
+ { return *_M_current; }
+
+ pointer
+ operator->() const
+ { return _M_current; }
+
+ copy_iterator&
+ operator++()
+ {
+ ++_M_current;
+ return *this;
+ }
+
+ copy_iterator
+ operator++(int)
+ {
+ copy_iterator __tmp = *this;
+ ++_M_current;
+ return __tmp;
+ }
+
+ copy_iterator&
+ operator--()
+ {
+ --_M_current;
+ return *this;
+ }
+
+ copy_iterator
+ operator--(int)
+ {
+ copy_iterator __tmp = *this;
+ --_M_current;
+ return __tmp;
+ }
+
+ copy_iterator
+ operator+(difference_type __n) const
+ { return copy_iterator(_M_current + __n); }
+
+ copy_iterator&
+ operator+=(difference_type __n)
+ {
+ _M_current += __n;
+ return *this;
+ }
+
+ copy_iterator
+ operator-(difference_type __n) const
+ { return copy_iterator(_M_current - __n); }
+
+ copy_iterator&
+ operator-=(difference_type __n)
+ {
+ _M_current -= __n;
+ return *this;
+ }
+
+ reference
+ operator[](difference_type __n) const
+ { return _M_current[__n]; }
+ };
+
+ // Note: See __normal_iterator operators note from Gaby to understand
+ // why there are always 2 versions for most of the copy_iterator
+ // operators.
+ template<typename _IteratorL, typename _IteratorR>
+ inline bool
+ operator==(const copy_iterator<_IteratorL>& __x,
+ const copy_iterator<_IteratorR>& __y)
+ { return __x.base() == __y.base(); }
+
+ template<typename _Iterator>
+ inline bool
+ operator==(const copy_iterator<_Iterator>& __x,
+ const copy_iterator<_Iterator>& __y)
+ { return __x.base() == __y.base(); }
+
+ template<typename _IteratorL, typename _IteratorR>
+ inline bool
+ operator!=(const copy_iterator<_IteratorL>& __x,
+ const copy_iterator<_IteratorR>& __y)
+ { return !(__x == __y); }
+
+ template<typename _Iterator>
+ inline bool
+ operator!=(const copy_iterator<_Iterator>& __x,
+ const copy_iterator<_Iterator>& __y)
+ { return !(__x == __y); }
+
+ template<typename _IteratorL, typename _IteratorR>
+ inline bool
+ operator<(const copy_iterator<_IteratorL>& __x,
+ const copy_iterator<_IteratorR>& __y)
+ { return __x.base() < __y.base(); }
+
+ template<typename _Iterator>
+ inline bool
+ operator<(const copy_iterator<_Iterator>& __x,
+ const copy_iterator<_Iterator>& __y)
+ { return __x.base() < __y.base(); }
+
+ template<typename _IteratorL, typename _IteratorR>
+ inline bool
+ operator<=(const copy_iterator<_IteratorL>& __x,
+ const copy_iterator<_IteratorR>& __y)
+ { return !(__y < __x); }
+
+ template<typename _Iterator>
+ inline bool
+ operator<=(const copy_iterator<_Iterator>& __x,
+ const copy_iterator<_Iterator>& __y)
+ { return !(__y < __x); }
+
+ template<typename _IteratorL, typename _IteratorR>
+ inline bool
+ operator>(const copy_iterator<_IteratorL>& __x,
+ const copy_iterator<_IteratorR>& __y)
+ { return __y < __x; }
+
+ template<typename _Iterator>
+ inline bool
+ operator>(const copy_iterator<_Iterator>& __x,
+ const copy_iterator<_Iterator>& __y)
+ { return __y < __x; }
+
+ template<typename _IteratorL, typename _IteratorR>
+ inline bool
+ operator>=(const copy_iterator<_IteratorL>& __x,
+ const copy_iterator<_IteratorR>& __y)
+ { return !(__x < __y); }
+
+ template<typename _Iterator>
+ inline bool
+ operator>=(const copy_iterator<_Iterator>& __x,
+ const copy_iterator<_Iterator>& __y)
+ { return !(__x < __y); }
+
+ // DR 685.
+ template<typename _IteratorL, typename _IteratorR>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ inline auto
+#else
+ inline typename copy_iterator<_IteratorL>::difference_type
+#endif
+ operator-(const copy_iterator<_IteratorL>& __x,
+ const copy_iterator<_IteratorR>& __y)
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ -> decltype(__x.base() - __y.base())
+#endif
+ { return __x.base() - __y.base(); }
+
+ template<typename _Iterator>
+ inline typename copy_iterator<_Iterator>::difference_type
+ operator-(const copy_iterator<_Iterator>& __x,
+ const copy_iterator<_Iterator>& __y)
+ { return __x.base() - __y.base(); }
+
+ template<typename _Iterator>
+ inline copy_iterator<_Iterator>
+ operator+(typename copy_iterator<_Iterator>::difference_type __n,
+ const copy_iterator<_Iterator>& __x)
+ { return __x + __n; }
+
+ template<typename _Iterator>
+ inline copy_iterator<_Iterator>
+ make_copy_iterator(_Iterator __i)
+ { return copy_iterator<_Iterator>(__i); }
+
+} // namespace __gnu_test
+#endif
Property changes on: testsuite/util/testsuite_counter_type.h
___________________________________________________________________
Added: svn:eol-style
+ native
Index: testsuite/25_algorithms/lower_bound/4.cc
===================================================================
--- testsuite/25_algorithms/lower_bound/4.cc (revision 0)
+++ testsuite/25_algorithms/lower_bound/4.cc (revision 0)
@@ -0,0 +1,230 @@
+// { dg-add-options no_pch }
+// { dg-options "-fno-elide-constructors" }
+// Copyright (C) 2012 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/>.
+
+// 25.3.3 [lib.alg.binary.search] Binary search algorithms.
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+#define LESS_OPERATOR_TAKES_COPY
+#include <testsuite_counter_type.h>
+
+//#define _ELIDE_CONSTRUCTORS
+//#define _WITHOUT_PATCH
+
+bool test __attribute__((unused)) = true;
+
+// 25.3.3.1 lower_bound, with and without comparison predicate
+
+void
+test01()
+{
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ counter_type* p = lower_bound(array, array + size, middle);
+ VERIFY( p == array + size / 2 );
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ VERIFY( counter_type::copy_count == 6 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+#else
+ VERIFY( counter_type::copy_count == 6 );
+ VERIFY( counter_type::move_count == 0 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+void
+test02()
+{
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ lower_bound(make_copy_iterator(array),
+ make_copy_iterator(array + size),
+ middle);
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# ifdef _WITHOUT_PATCH
+# ifdef _ELIDE_CONSTRUCTORS
+ VERIFY( counter_type::copy_count == 6 );
+# else
+ VERIFY( counter_type::copy_count == 9 );
+# endif
+# else
+# ifdef _ELIDE_CONSTRUCTORS
+ VERIFY( counter_type::copy_count == 9 );
+# else
+ VERIFY( counter_type::copy_count == 12 );
+# endif
+# endif
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+#else
+ VERIFY( counter_type::copy_count == 6 );
+# ifdef _WITHOUT_PATCH
+# ifdef _ELIDE_CONSTRUCTORS
+ VERIFY( counter_type::move_count == 0 );
+# else
+ VERIFY( counter_type::move_count == 3 );
+# endif
+# else
+ VERIFY( counter_type::move_count == 3 );
+# endif
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+void
+test03()
+{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ lower_bound(std::make_move_iterator(array),
+ std::make_move_iterator(array + size),
+ middle);
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+ VERIFY( counter_type::copy_count == 3 );
+ VERIFY( counter_type::move_count == 3 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+void
+test04()
+{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ lower_bound(std::make_move_iterator(make_copy_iterator(array)),
+ std::make_move_iterator(make_copy_iterator(array + size)),
+ middle);
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+ VERIFY( counter_type::copy_count == 6 );
+ VERIFY( counter_type::move_count == 3 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ return 0;
+}
Index: testsuite/25_algorithms/lower_bound/3.cc
===================================================================
--- testsuite/25_algorithms/lower_bound/3.cc (revision 0)
+++ testsuite/25_algorithms/lower_bound/3.cc (revision 0)
@@ -0,0 +1,216 @@
+// { dg-add-options no_pch }
+// { dg-options "-fno-elide-constructors" }
+// Copyright (C) 2012 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/>.
+
+// 25.3.3 [lib.alg.binary.search] Binary search algorithms.
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_counter_type.h>
+
+//#define _ELIDE_CONSTRUCTORS
+//#define _WITHOUT_PATCH
+
+bool test __attribute__((unused)) = true;
+
+// 25.3.3.1 lower_bound, with and without comparison predicate
+
+void
+test01()
+{
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ lower_bound(array, array + size, middle);
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ VERIFY( counter_type::copy_count == 0 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+#else
+ VERIFY( counter_type::copy_count == 0 );
+ VERIFY( counter_type::move_count == 0 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+void
+test02()
+{
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ lower_bound(make_copy_iterator(array),
+ make_copy_iterator(array + size),
+ middle);
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# ifdef _WITHOUT_PATCH
+ VERIFY( counter_type::copy_count == 3 );
+# else
+# ifdef _ELIDE_CONSTRUCTORS
+ VERIFY( counter_type::copy_count == 3 );
+# else
+ VERIFY( counter_type::copy_count == 6 );
+# endif
+# endif
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+#else
+ VERIFY( counter_type::copy_count == 3 );
+ VERIFY( counter_type::move_count == 0 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+
+void
+test03()
+{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ lower_bound(std::make_move_iterator(array),
+ std::make_move_iterator(array + size),
+ middle);
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+ VERIFY( counter_type::copy_count == 0 );
+ VERIFY( counter_type::move_count == 0 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+void
+test04()
+{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ using std::lower_bound;
+ using __gnu_test::counter_type;
+
+ counter_type array[] =
+ {
+ counter_type(0),
+ counter_type(1),
+ counter_type(2),
+ counter_type(3),
+ counter_type(4),
+ counter_type(5),
+ counter_type(6)
+ };
+
+
+ const std::size_t size = sizeof(array) / sizeof(counter_type);
+
+ const counter_type middle = array[size / 2];
+
+ counter_type::reset();
+
+ lower_bound(std::make_move_iterator(make_copy_iterator(array)),
+ std::make_move_iterator(make_copy_iterator(array + size)),
+ middle);
+
+ VERIFY( counter_type::default_count == 0 );
+ VERIFY( counter_type::specialize_count == 0 );
+ VERIFY( counter_type::copy_count == 3 );
+ VERIFY( counter_type::move_count == 0 );
+ VERIFY( counter_type::copy_assign_count == 0 );
+ VERIFY( counter_type::move_assign_count == 0 );
+ VERIFY( counter_type::less_compare_count == 3 );
+ VERIFY( counter_type::move_less_compare_count == 0 );
+#endif
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ return 0;
+}