commit 99d7d1ebce9f290220966e138ef9b9e741878917
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Jan 19 17:05:34 2015 +0000
Implement N3657: heterogeneous lookup in associative containers.
* include/bits/stl_map.h (map::find<>, map::count<>,
map::lower_bound<>, map::upper_bound<>, map::equal_range<>): New
member function templates to perform heterogeneous lookup.
* include/bits/stl_multimap.h (multimap::find<>, multimap::count<>,
multimap::lower_bound<>, multimap::upper_bound<>,
multimap::equal_range<>): Likewise.
* include/bits/stl_multiset.h (multiset::find<>, multiset::count<>,
multiset::lower_bound<>, multiset::upper_bound<>,
multiset::equal_range<>): Likewise.
* include/bits/stl_set.h (set::find<>, set::count<>,
set::lower_bound<>, set::upper_bound<>, set::equal_range<>): Likewise.
* include/bits/stl_tree.h (_Rb_tree::_S_lower_bound_tr,
_Rb_tree::_S_upper_bound_tr, _Rb_tree::_M_find_tr,
_Rb_tree::_M_count_tr, _Rb_tree::_M_lower_bound_tr,
_Rb_tree::_M_upper_bound_tr, _Rb_tree::_M_equal_range_tr): Likewise.
* testsuite/23_containers/map/operations/2.cc: New.
* testsuite/23_containers/multimap/operations/2.cc: New.
* testsuite/23_containers/multiset/operations/2.cc: New.
* testsuite/23_containers/set/operations/2.cc: New.
@@ -824,6 +824,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return value_compare(_M_t.key_comp()); }
// [23.3.1.3] map operations
+
+ //@{
/**
* @brief Tries to locate an element in a %map.
* @param __x Key of (key, value) %pair to be located.
@@ -835,10 +837,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* pointing to the sought after %pair. If unsuccessful it returns the
* past-the-end ( @c end() ) iterator.
*/
+
iterator
find(const key_type& __x)
{ return _M_t.find(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Tries to locate an element in a %map.
* @param __x Key of (key, value) %pair to be located.
@@ -850,10 +862,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* iterator pointing to the sought after %pair. If unsuccessful it
* returns the past-the-end ( @c end() ) iterator.
*/
+
const_iterator
find(const key_type& __x) const
{ return _M_t.find(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the number of elements with given key.
* @param __x Key of (key, value) pairs to be located.
@@ -866,6 +888,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.find(__x) == _M_t.end() ? 0 : 1; }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x))
+ { return _M_t._M_find_tr(__x) == _M_t.end() ? 0 : 1; }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the beginning of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -881,6 +912,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x)
{ return _M_t.lower_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x)
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the beginning of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -896,6 +937,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the end of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -906,6 +957,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x)
{ return _M_t.upper_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x)
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the end of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -916,6 +977,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds a subsequence matching given key.
* @param __x Key of (key, value) pairs to be located.
@@ -935,6 +1006,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_t.equal_range(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x)
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds a subsequence matching given key.
* @param __x Key of (key, value) pairs to be located.
@@ -954,6 +1035,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x) const
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+#endif
+ //@}
+
template<typename _K1, typename _T1, typename _C1, typename _A1>
friend bool
operator==(const map<_K1, _T1, _C1, _A1>&,
@@ -734,6 +734,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return value_compare(_M_t.key_comp()); }
// multimap operations
+
+ //@{
/**
* @brief Tries to locate an element in a %multimap.
* @param __x Key of (key, value) pair to be located.
@@ -749,6 +751,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x)
{ return _M_t.find(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Tries to locate an element in a %multimap.
* @param __x Key of (key, value) pair to be located.
@@ -764,6 +775,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
find(const key_type& __x) const
{ return _M_t.find(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the number of elements with given key.
* @param __x Key of (key, value) pairs to be located.
@@ -773,6 +793,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.count(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x))
+ { return _M_t._M_count_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the beginning of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -788,6 +817,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x)
{ return _M_t.lower_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x)
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the beginning of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -803,6 +842,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the end of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -813,6 +862,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x)
{ return _M_t.upper_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x)
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds the end of a subsequence matching given key.
* @param __x Key of (key, value) pair to be located.
@@ -823,6 +882,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds a subsequence matching given key.
* @param __x Key of (key, value) pairs to be located.
@@ -840,6 +909,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x)
{ return _M_t.equal_range(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x)
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+#endif
+ //@}
+
+ //@{
/**
* @brief Finds a subsequence matching given key.
* @param __x Key of (key, value) pairs to be located.
@@ -857,6 +936,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x) const
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+#endif
+ //@}
+
template<typename _K1, typename _T1, typename _C1, typename _A1>
friend bool
operator==(const multimap<_K1, _T1, _C1, _A1>&,
@@ -636,6 +636,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// multiset operations:
+ //@{
/**
* @brief Finds the number of elements with given key.
* @param __x Key of elements to be located.
@@ -645,6 +646,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.count(__x); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x))
+ { return _M_t._M_count_tr(__x); }
+#endif
+ //@}
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 214. set::find() missing const overload
//@{
@@ -666,6 +675,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const_iterator
find(const key_type& __x) const
{ return _M_t.find(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+#endif
//@}
//@{
@@ -687,6 +708,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const_iterator
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x)
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+#endif
//@}
//@{
@@ -703,6 +738,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const_iterator
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x)
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+#endif
//@}
//@{
@@ -728,6 +777,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::pair<const_iterator, const_iterator>
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x)
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x) const
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+#endif
//@}
template<typename _K1, typename _C1, typename _A1>
@@ -651,6 +651,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// set operations:
+ //@{
/**
* @brief Finds the number of elements.
* @param __x Element to located.
@@ -663,6 +664,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
count(const key_type& __x) const
{ return _M_t.find(__x) == _M_t.end() ? 0 : 1; }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ count(const _Kt& __x) const
+ -> decltype(_M_t._M_count_tr(__x))
+ { return _M_t._M_find_tr(__x) == _M_t.end() ? 0 : 1; }
+#endif
+ //@}
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 214. set::find() missing const overload
//@{
@@ -684,6 +694,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const_iterator
find(const key_type& __x) const
{ return _M_t.find(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
+ { return _M_t._M_find_tr(__x); }
+#endif
//@}
//@{
@@ -705,6 +727,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const_iterator
lower_bound(const key_type& __x) const
{ return _M_t.lower_bound(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x)
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ lower_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_lower_bound_tr(__x))
+ { return _M_t._M_lower_bound_tr(__x); }
+#endif
//@}
//@{
@@ -721,6 +757,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const_iterator
upper_bound(const key_type& __x) const
{ return _M_t.upper_bound(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x)
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ upper_bound(const _Kt& __x) const
+ -> decltype(_M_t._M_upper_bound_tr(__x))
+ { return _M_t._M_upper_bound_tr(__x); }
+#endif
//@}
//@{
@@ -746,6 +796,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::pair<const_iterator, const_iterator>
equal_range(const key_type& __x) const
{ return _M_t.equal_range(__x); }
+
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x)
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+
+ template<typename _Kt>
+ auto
+ equal_range(const _Kt& __x) const
+ -> decltype(_M_t._M_equal_range_tr(__x))
+ { return _M_t._M_equal_range_tr(__x); }
+#endif
//@}
template<typename _K1, typename _C1, typename _A1>
@@ -1118,6 +1118,137 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
pair<const_iterator, const_iterator>
equal_range(const key_type& __k) const;
+#if __cplusplus > 201103L
+ template<typename _Cmp, typename _Kt, typename = __void_t<>>
+ struct __is_transparent { };
+
+ template<typename _Cmp, typename _Kt>
+ struct
+ __is_transparent<_Cmp, _Kt, __void_t<typename _Cmp::is_transparent>>
+ { typedef void type; };
+
+ static auto _S_iter(_Link_type __x) { return iterator(__x); }
+
+ static auto _S_iter(_Const_Link_type __x) { return const_iterator(__x); }
+
+ template<typename _Cmp, typename _Link, typename _Kt>
+ static auto
+ _S_lower_bound_tr(_Cmp& __cmp, _Link __x, _Link __y, const _Kt& __k)
+ {
+ while (__x != 0)
+ if (!__cmp(_S_key(__x), __k))
+ __y = __x, __x = _S_left(__x);
+ else
+ __x = _S_right(__x);
+ return _S_iter(__y);
+ }
+
+ template<typename _Cmp, typename _Link, typename _Kt>
+ static auto
+ _S_upper_bound_tr(_Cmp& __cmp, _Link __x, _Link __y, const _Kt& __k)
+ {
+ while (__x != 0)
+ if (__cmp(__k, _S_key(__x)))
+ __y = __x, __x = _S_left(__x);
+ else
+ __x = _S_right(__x);
+ return _S_iter(__y);
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ iterator
+ _M_find_tr(const _Kt& __k)
+ {
+ auto& __cmp = _M_impl._M_key_compare;
+ auto __j = _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+ return (__j == end() || __cmp(__k, _S_key(__j._M_node)))
+ ? end() : __j;
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ _M_find_tr(const _Kt& __k) const
+ {
+ auto& __cmp = _M_impl._M_key_compare;
+ auto __j = _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+ return (__j == end() || __cmp(__k, _S_key(__j._M_node)))
+ ? end() : __j;
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ size_type
+ _M_count_tr(const _Kt& __k) const
+ {
+ auto __p = _M_equal_range_tr(__k);
+ return std::distance(__p.first, __p.second);
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ iterator
+ _M_lower_bound_tr(const _Kt& __k)
+ {
+ auto& __cmp = _M_impl._M_key_compare;
+ return _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ _M_lower_bound_tr(const _Kt& __k) const
+ {
+ auto& __cmp = _M_impl._M_key_compare;
+ return _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ iterator
+ _M_upper_bound_tr(const _Kt& __k)
+ {
+ auto& __cmp = _M_impl._M_key_compare;
+ return _S_upper_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ _M_upper_bound_tr(const _Kt& __k) const
+ {
+ auto& __cmp = _M_impl._M_key_compare;
+ return _S_upper_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ pair<iterator, iterator>
+ _M_equal_range_tr(const _Kt& __k)
+ {
+ auto __low = _M_lower_bound_tr(__k);
+ auto __high = __low;
+ auto& __cmp = _M_impl._M_key_compare;
+ while (__high != end() && !__cmp(__k, _S_key(__high._M_node)))
+ ++__high;
+ return { __low, __high };
+ }
+
+ template<typename _Kt,
+ typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ pair<const_iterator, const_iterator>
+ _M_equal_range_tr(const _Kt& __k) const
+ {
+ auto __low = _M_lower_bound_tr(__k);
+ auto __high = __low;
+ auto& __cmp = _M_impl._M_key_compare;
+ while (__high != end() && !__cmp(__k, _S_key(__high._M_node)))
+ ++__high;
+ return { __low, __high };
+ }
+#endif
+
// Debugging.
bool
__rb_verify() const;
new file mode 100644
@@ -0,0 +1,140 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++14" }
+
+#include <map>
+#include <testsuite_hooks.h>
+
+struct Cmp
+{
+ typedef void is_transparent;
+
+ bool operator()(int i, long l) const { return i < l; }
+ bool operator()(long l, int i) const { return l < i; }
+ bool operator()(int i, int j) const { ++count; return i < j; }
+
+ static int count;
+};
+
+int Cmp::count = 0;
+
+using test_type = std::map<int, char, Cmp>;
+
+test_type x{ { 1, '2' }, { 3, '4' } };
+const test_type& cx = x;
+
+void
+test01()
+{
+ Cmp::count = 0;
+
+ auto it = x.find(1L);
+ VERIFY( it != x.end() && it->second == '2' );
+ it = x.find(2L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.find(3L);
+ VERIFY( cit != cx.end() && cit->second == '4' );
+ cit = cx.find(2L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test02()
+{
+ Cmp::count = 0;
+
+ auto n = x.count(1L);
+ VERIFY( n == 1 );
+ n = x.count(2L);
+ VERIFY( n == 0 );
+
+ auto cn = cx.count(3L);
+ VERIFY( cn == 1 );
+ cn = cx.count(2L);
+ VERIFY( cn == 0 );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test03()
+{
+ Cmp::count = 0;
+
+ auto it = x.lower_bound(1L);
+ VERIFY( it != x.end() && it->second == '2' );
+ it = x.lower_bound(2L);
+ VERIFY( it != x.end() && it->second == '4' );
+
+ auto cit = cx.lower_bound(1L);
+ VERIFY( cit != cx.end() && cit->second == '2' );
+ cit = cx.lower_bound(2L);
+ VERIFY( cit != cx.end() && cit->second == '4' );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test04()
+{
+ Cmp::count = 0;
+
+ auto it = x.upper_bound(1L);
+ VERIFY( it != x.end() && it->second == '4' );
+ it = x.upper_bound(3L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.upper_bound(1L);
+ VERIFY( cit != cx.end() && cit->second == '4' );
+ cit = cx.upper_bound(3L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test05()
+{
+ Cmp::count = 0;
+
+ auto it = x.equal_range(1L);
+ VERIFY( it.first != it.second && it.first->second == '2' );
+ it = x.equal_range(2L);
+ VERIFY( it.first == it.second && it.first != x.end() );
+
+ auto cit = cx.equal_range(1L);
+ VERIFY( cit.first != cit.second && cit.first->second == '2' );
+ cit = cx.equal_range(2L);
+ VERIFY( cit.first == cit.second && cit.first != cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+}
new file mode 100644
@@ -0,0 +1,141 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++14" }
+
+#include <map>
+#include <testsuite_hooks.h>
+
+struct Cmp
+{
+ typedef void is_transparent;
+
+ bool operator()(int i, long l) const { return i < l; }
+ bool operator()(long l, int i) const { return l < i; }
+ bool operator()(int i, int j) const { ++count; return i < j; }
+
+ static int count;
+};
+
+int Cmp::count = 0;
+
+using test_type = std::multimap<int, char, Cmp>;
+
+test_type x{ { 1, '2' }, { 3, '4' }, { 3, '5' } };
+const test_type& cx = x;
+
+void
+test01()
+{
+ Cmp::count = 0;
+
+ auto it = x.find(1L);
+ VERIFY( it != x.end() && it->second == '2' );
+ it = x.find(2L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.find(3L);
+ VERIFY( cit != cx.end() && cit->second == '4' );
+ cit = cx.find(2L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test02()
+{
+ Cmp::count = 0;
+
+ auto n = x.count(1L);
+ VERIFY( n == 1 );
+ n = x.count(2L);
+ VERIFY( n == 0 );
+
+ auto cn = cx.count(3L);
+ VERIFY( cn == 2 );
+ cn = cx.count(2L);
+ VERIFY( cn == 0 );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test03()
+{
+ Cmp::count = 0;
+
+ auto it = x.lower_bound(1L);
+ VERIFY( it != x.end() && it->second == '2' );
+ it = x.lower_bound(2L);
+ VERIFY( it != x.end() && it->second == '4' );
+
+ auto cit = cx.lower_bound(1L);
+ VERIFY( cit != cx.end() && cit->second == '2' );
+ cit = cx.lower_bound(2L);
+ VERIFY( cit != cx.end() && cit->second == '4' );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test04()
+{
+ Cmp::count = 0;
+
+ auto it = x.upper_bound(1L);
+ VERIFY( it != x.end() && it->second == '4' );
+ it = x.upper_bound(3L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.upper_bound(1L);
+ VERIFY( cit != cx.end() && cit->second == '4' );
+ cit = cx.upper_bound(3L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test05()
+{
+ Cmp::count = 0;
+
+ auto it = x.equal_range(1L);
+ VERIFY( it.first != it.second && it.first->second == '2' );
+ it = x.equal_range(2L);
+ VERIFY( it.first == it.second && it.first != x.end() );
+
+ auto cit = cx.equal_range(3L);
+ VERIFY( cit.first != cit.second && cit.first->second == '4' );
+ VERIFY( std::distance(cit.first, cit.second) == 2 );
+ cit = cx.equal_range(2L);
+ VERIFY( cit.first == cit.second && cit.first != cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+}
new file mode 100644
@@ -0,0 +1,141 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++14" }
+
+#include <set>
+#include <testsuite_hooks.h>
+
+struct Cmp
+{
+ typedef void is_transparent;
+
+ bool operator()(int i, long l) const { return i < l; }
+ bool operator()(long l, int i) const { return l < i; }
+ bool operator()(int i, int j) const { ++count; return i < j; }
+
+ static int count;
+};
+
+int Cmp::count = 0;
+
+using test_type = std::multiset<int, Cmp>;
+
+test_type x{ 1, 3, 3, 5 };
+const test_type& cx = x;
+
+void
+test01()
+{
+ Cmp::count = 0;
+
+ auto it = x.find(1L);
+ VERIFY( it != x.end() && *it == 1 );
+ it = x.find(2L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.find(3L);
+ VERIFY( cit != cx.end() && *cit == 3 );
+ cit = cx.find(2L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test02()
+{
+ Cmp::count = 0;
+
+ auto n = x.count(1L);
+ VERIFY( n == 1 );
+ n = x.count(2L);
+ VERIFY( n == 0 );
+
+ auto cn = cx.count(3L);
+ VERIFY( cn == 2 );
+ cn = cx.count(2L);
+ VERIFY( cn == 0 );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test03()
+{
+ Cmp::count = 0;
+
+ auto it = x.lower_bound(1L);
+ VERIFY( it != x.end() && *it == 1 );
+ it = x.lower_bound(2L);
+ VERIFY( it != x.end() && *it == 3 );
+
+ auto cit = cx.lower_bound(1L);
+ VERIFY( cit != cx.end() && *cit == 1 );
+ cit = cx.lower_bound(2L);
+ VERIFY( cit != cx.end() && *cit == 3 );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test04()
+{
+ Cmp::count = 0;
+
+ auto it = x.upper_bound(1L);
+ VERIFY( it != x.end() && *it == 3 );
+ it = x.upper_bound(5L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.upper_bound(1L);
+ VERIFY( cit != cx.end() && *cit == 3 );
+ cit = cx.upper_bound(5L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test05()
+{
+ Cmp::count = 0;
+
+ auto it = x.equal_range(1L);
+ VERIFY( it.first != it.second && *it.first == 1 );
+ it = x.equal_range(2L);
+ VERIFY( it.first == it.second && it.first != x.end() );
+
+ auto cit = cx.equal_range(3L);
+ VERIFY( cit.first != cit.second && *cit.first == 3 );
+ VERIFY( std::distance(cit.first, cit.second) == 2 );
+ cit = cx.equal_range(2L);
+ VERIFY( cit.first == cit.second && cit.first != cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+}
new file mode 100644
@@ -0,0 +1,140 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++14" }
+
+#include <set>
+#include <testsuite_hooks.h>
+
+struct Cmp
+{
+ typedef void is_transparent;
+
+ bool operator()(int i, long l) const { return i < l; }
+ bool operator()(long l, int i) const { return l < i; }
+ bool operator()(int i, int j) const { ++count; return i < j; }
+
+ static int count;
+};
+
+int Cmp::count = 0;
+
+using test_type = std::set<int, Cmp>;
+
+test_type x{ 1, 3, 5 };
+const test_type& cx = x;
+
+void
+test01()
+{
+ Cmp::count = 0;
+
+ auto it = x.find(1L);
+ VERIFY( it != x.end() && *it == 1 );
+ it = x.find(2L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.find(3L);
+ VERIFY( cit != cx.end() && *cit == 3 );
+ cit = cx.find(2L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test02()
+{
+ Cmp::count = 0;
+
+ auto n = x.count(1L);
+ VERIFY( n == 1 );
+ n = x.count(2L);
+ VERIFY( n == 0 );
+
+ auto cn = cx.count(3L);
+ VERIFY( cn == 1 );
+ cn = cx.count(2L);
+ VERIFY( cn == 0 );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test03()
+{
+ Cmp::count = 0;
+
+ auto it = x.lower_bound(1L);
+ VERIFY( it != x.end() && *it == 1 );
+ it = x.lower_bound(2L);
+ VERIFY( it != x.end() && *it == 3 );
+
+ auto cit = cx.lower_bound(1L);
+ VERIFY( cit != cx.end() && *cit == 1 );
+ cit = cx.lower_bound(2L);
+ VERIFY( cit != cx.end() && *cit == 3 );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test04()
+{
+ Cmp::count = 0;
+
+ auto it = x.upper_bound(1L);
+ VERIFY( it != x.end() && *it == 3 );
+ it = x.upper_bound(5L);
+ VERIFY( it == x.end() );
+
+ auto cit = cx.upper_bound(1L);
+ VERIFY( cit != cx.end() && *cit == 3 );
+ cit = cx.upper_bound(5L);
+ VERIFY( cit == cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+void
+test05()
+{
+ Cmp::count = 0;
+
+ auto it = x.equal_range(1L);
+ VERIFY( it.first != it.second && *it.first == 1 );
+ it = x.equal_range(2L);
+ VERIFY( it.first == it.second && it.first != x.end() );
+
+ auto cit = cx.equal_range(1L);
+ VERIFY( cit.first != cit.second && *cit.first == 1 );
+ cit = cx.equal_range(2L);
+ VERIFY( cit.first == cit.second && cit.first != cx.end() );
+
+ VERIFY( Cmp::count == 0);
+}
+
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+}