Implement N3657: heterogeneous lookup in associative containers.
authorJonathan Wakely <jwakely@redhat.com>
Tue, 20 Jan 2015 11:50:58 +0000 (11:50 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 20 Jan 2015 11:50:58 +0000 (11:50 +0000)
* 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.

From-SVN: r219888

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_map.h
libstdc++-v3/include/bits/stl_multimap.h
libstdc++-v3/include/bits/stl_multiset.h
libstdc++-v3/include/bits/stl_set.h
libstdc++-v3/include/bits/stl_tree.h
libstdc++-v3/testsuite/23_containers/map/operations/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/multimap/operations/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/multiset/operations/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/set/operations/2.cc [new file with mode: 0644]

index 7410bbccfe0e26d1bceb05de5fbf0fd86a8d8598..3274825b5938d50b59a538d71bec13c9e62ee5b4 100644 (file)
@@ -1,3 +1,25 @@
+2015-01-20  Jonathan Wakely  <jwakely@redhat.com>
+
+       * 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.
+
 2015-01-20  Jonathan Wakely  <jwakely@redhat.com>
 
        * config/abi/pre/gnu.ver: Export new constructors.
index 3bac4e0898271b652f2ce39236aafd18128a6a3b..df18973931ec366c59b12734deb5f7fec2a793da 100644 (file)
@@ -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>&,
index 5a81f8ffad657e51023c4e578a1742f1bc15508c..f3d21ab8bea156fa51fc90c64451ed15b3f850bc 100644 (file)
@@ -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>&,
index be04221bd1269d04d379951df87fe09c3b58a54b..7e92836aaecf2e16b5545ff8d03ff2fb522cf9d8 100644 (file)
@@ -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>
index 3944bcd52f7344d453b2bb731d7a696f42b2c85a..518923435702e799ad0d23fc24e1edb470d8cdac 100644 (file)
@@ -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>
index e78b2db1726a00a114817e048932e1367a89a407..5ca8e28ef43af3b9309680af6670a7b01712f20f 100644 (file)
@@ -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;
diff --git a/libstdc++-v3/testsuite/23_containers/map/operations/2.cc b/libstdc++-v3/testsuite/23_containers/map/operations/2.cc
new file mode 100644 (file)
index 0000000..6cc277a
--- /dev/null
@@ -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();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/operations/2.cc b/libstdc++-v3/testsuite/23_containers/multimap/operations/2.cc
new file mode 100644 (file)
index 0000000..67c3bfd
--- /dev/null
@@ -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();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/operations/2.cc b/libstdc++-v3/testsuite/23_containers/multiset/operations/2.cc
new file mode 100644 (file)
index 0000000..ff2748f
--- /dev/null
@@ -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();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/set/operations/2.cc b/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
new file mode 100644 (file)
index 0000000..752bc7d
--- /dev/null
@@ -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();
+}