* [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
@ 2015-01-19 17:43 Jonathan Wakely
2015-01-20 12:08 ` Jonathan Wakely
0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2015-01-19 17:43 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 174 bytes --]
This is the last missing piece of the C++14 library, as proposed in
http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2013/n3657.htm
Tested x86_64-linux, *not* committed.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 35528 bytes --]
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.
diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index 3bac4e0..df18973 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -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>&,
diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h
index 5a81f8f..f3d21ab 100644
--- a/libstdc++-v3/include/bits/stl_multimap.h
+++ b/libstdc++-v3/include/bits/stl_multimap.h
@@ -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>&,
diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h
index be04221..7e92836 100644
--- a/libstdc++-v3/include/bits/stl_multiset.h
+++ b/libstdc++-v3/include/bits/stl_multiset.h
@@ -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>
diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h
index 3944bcd..5189234 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -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>
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index e78b2db..5ca8e28 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -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
index 0000000..6cc277a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/map/operations/2.cc
@@ -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
index 0000000..67c3bfd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multimap/operations/2.cc
@@ -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
index 0000000..ff2748f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multiset/operations/2.cc
@@ -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
index 0000000..752bc7d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
@@ -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();
+}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-19 17:43 [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers Jonathan Wakely
@ 2015-01-20 12:08 ` Jonathan Wakely
2015-01-21 23:03 ` François Dumont
0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2015-01-20 12:08 UTC (permalink / raw)
To: libstdc++, gcc-patches
On 19/01/15 17:16 +0000, Jonathan Wakely wrote:
>This is the last missing piece of the C++14 library, as proposed in
>http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2013/n3657.htm
>
>Tested x86_64-linux, *not* committed.
Now committed to trunk.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-20 12:08 ` Jonathan Wakely
@ 2015-01-21 23:03 ` François Dumont
2015-01-22 4:10 ` Jonathan Wakely
2015-01-22 4:23 ` Jonathan Wakely
0 siblings, 2 replies; 10+ messages in thread
From: François Dumont @ 2015-01-21 23:03 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1160 bytes --]
On 20/01/2015 13:00, Jonathan Wakely wrote:
> On 19/01/15 17:16 +0000, Jonathan Wakely wrote:
>> This is the last missing piece of the C++14 library, as proposed in
>> http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2013/n3657.htm
>>
>> Tested x86_64-linux, *not* committed.
>
> Now committed to trunk.
>
Is it ok then to commit attached patch to do the same for debug mode ?
And also for profile mode later when I have it ready (this WE I think) ?
2015-01-22 François Dumont <fdumont@gcc.gnu.org>
* include/debug/stl_map.h (map::find<>,
map::lower_bound<>, map::upper_bound<>, map::equal_range<>): New
member function templates to perform heterogeneous lookup.
* include/debug/stl_multimap.h (multimap::find<>,
multimap::lower_bound<>, multimap::upper_bound<>,
multimap::equal_range<>): Likewise.
* include/debug/stl_multiset.h (multiset::find<>,
multiset::lower_bound<>, multiset::upper_bound<>,
multiset::equal_range<>): Likewise.
* include/debug/stl_set.h (set::find<>,
set::lower_bound<>, set::upper_bound<>, set::equal_range<>): Likewise.
Tested under Linux x86_64 debug mode.
François
[-- Attachment #2: debug_asso_cont.patch --]
[-- Type: text/x-patch, Size: 11374 bytes --]
Index: include/debug/map.h
===================================================================
--- include/debug/map.h (revision 219967)
+++ include/debug/map.h (working copy)
@@ -412,10 +412,24 @@
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ find(const _Kt& __x)
+ { return iterator(_Base::find(__x), this); }
+#endif
+
const_iterator
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ const_iterator
+ find(const _Kt& __x) const
+ { return const_iterator(_Base::find(__x), this); }
+#endif
+
using _Base::count;
iterator
@@ -422,18 +436,46 @@
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return iterator(_Base::lower_bound(__x), this); }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return const_iterator(_Base::lower_bound(__x), this); }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return iterator(_Base::upper_bound(__x), this); }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return const_iterator(_Base::upper_bound(__x), this); }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -443,6 +485,18 @@
iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ std::pair<_Base_iterator, _Base_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(iterator(__res.first, this),
+ iterator(__res.second, this));
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -452,6 +506,18 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ std::pair<_Base_const_iterator, _Base_const_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(const_iterator(__res.first, this),
+ const_iterator(__res.second, this));
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/multimap.h
===================================================================
--- include/debug/multimap.h (revision 219967)
+++ include/debug/multimap.h (working copy)
@@ -393,10 +393,24 @@
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ find(const _Kt& __x)
+ { return iterator(_Base::find(__x), this); }
+#endif
+
const_iterator
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ const_iterator
+ find(const _Kt& __x) const
+ { return const_iterator(_Base::find(__x), this); }
+#endif
+
using _Base::count;
iterator
@@ -403,18 +417,46 @@
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return iterator(_Base::lower_bound(__x), this); }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return const_iterator(_Base::lower_bound(__x), this); }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return iterator(_Base::upper_bound(__x), this); }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return const_iterator(_Base::upper_bound(__x), this); }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -424,6 +466,18 @@
iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ std::pair<_Base_iterator, _Base_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(iterator(__res.first, this),
+ iterator(__res.second, this));
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -433,6 +487,18 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ std::pair<_Base_const_iterator, _Base_const_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(const_iterator(__res.first, this),
+ const_iterator(__res.second, this));
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/set.h
===================================================================
--- include/debug/set.h (revision 219967)
+++ include/debug/set.h (working copy)
@@ -393,6 +393,18 @@
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ find(const _Kt& __x)
+ { return iterator(_Base::find(__x), this); }
+
+ template<typename _Kt>
+ const_iterator
+ find(const _Kt& __x) const
+ { return const_iterator(_Base::find(__x), this); }
+#endif
+
using _Base::count;
iterator
@@ -405,6 +417,18 @@
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return iterator(_Base::lower_bound(__x), this); }
+
+ template<typename _Kt>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return const_iterator(_Base::lower_bound(__x), this); }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
@@ -415,6 +439,18 @@
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return iterator(_Base::upper_bound(__x), this); }
+
+ template<typename _Kt>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return const_iterator(_Base::upper_bound(__x), this); }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -429,12 +465,34 @@
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
- std::pair<_Base_iterator, _Base_iterator> __res =
+ std::pair<_Base_const_iterator, _Base_const_iterator> __res =
_Base::equal_range(__x);
return std::make_pair(const_iterator(__res.first, this),
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ std::pair<_Base_iterator, _Base_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(iterator(__res.first, this),
+ iterator(__res.second, this));
+ }
+
+ template<typename _Kt>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ std::pair<_Base_const_iterator, _Base_const_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(const_iterator(__res.first, this),
+ const_iterator(__res.second, this));
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/multiset.h
===================================================================
--- include/debug/multiset.h (revision 219967)
+++ include/debug/multiset.h (working copy)
@@ -386,6 +386,18 @@
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ find(const _Kt& __x)
+ { return iterator(_Base::find(__x), this); }
+
+ template<typename _Kt>
+ const_iterator
+ find(const _Kt& __x) const
+ { return const_iterator(_Base::find(__x), this); }
+#endif
+
using _Base::count;
iterator
@@ -398,6 +410,18 @@
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return iterator(_Base::lower_bound(__x), this); }
+
+ template<typename _Kt>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return const_iterator(_Base::lower_bound(__x), this); }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
@@ -408,6 +432,18 @@
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return iterator(_Base::upper_bound(__x), this); }
+
+ template<typename _Kt>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return const_iterator(_Base::upper_bound(__x), this); }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -428,6 +464,28 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ std::pair<_Base_iterator, _Base_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(iterator(__res.first, this),
+ iterator(__res.second, this));
+ }
+
+ template<typename _Kt>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ std::pair<_Base_const_iterator, _Base_const_iterator> __res =
+ _Base::equal_range(__x);
+ return std::make_pair(const_iterator(__res.first, this),
+ const_iterator(__res.second, this));
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-21 23:03 ` François Dumont
@ 2015-01-22 4:10 ` Jonathan Wakely
2015-01-22 4:23 ` Jonathan Wakely
1 sibling, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2015-01-22 4:10 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 21/01/15 23:30 +0100, François Dumont wrote:
>On 20/01/2015 13:00, Jonathan Wakely wrote:
>>On 19/01/15 17:16 +0000, Jonathan Wakely wrote:
>>>This is the last missing piece of the C++14 library, as proposed in
>>>http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2013/n3657.htm
>>>
>>>Tested x86_64-linux, *not* committed.
>>
>>Now committed to trunk.
>>
>Is it ok then to commit attached patch to do the same for debug mode ?
Definitely not like that, your patch adds the functions
unconditionally, but they must not participate in overload resolution
unless the comparison function defines an is_transparent member type.
I won't be too concerned if these new functions aren't available in
Debug Mode for the next release, we can add them later.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-21 23:03 ` François Dumont
2015-01-22 4:10 ` Jonathan Wakely
@ 2015-01-22 4:23 ` Jonathan Wakely
2015-01-25 10:11 ` François Dumont
1 sibling, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2015-01-22 4:23 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 21/01/15 23:30 +0100, François Dumont wrote:
>+#if __cplusplus > 201103L
>+ template<typename _Kt>
>+ std::pair<iterator, iterator>
>+ equal_range(const _Kt& __x)
>+ {
>+ std::pair<_Base_iterator, _Base_iterator> __res =
>+ _Base::equal_range(__x);
>+ return std::make_pair(iterator(__res.first, this),
>+ iterator(__res.second, this));
>+ }
BTW, this is C++14 code, what's wrong with:
template<typename _Kt>
std::pair<const_iterator, const_iterator>
equal_range(const _Kt& __x) const
{
auto __res = _Base::equal_range(__x);
return { iterator(__res.first, this), iterator(__res.second, this) };
}
Or even:
template<typename _Kt>
std::pair<const_iterator, const_iterator>
equal_range(const _Kt& __x) const
{
auto __res = _Base::equal_range(__x);
return { { __res.first, this }, {__res.second, this} };
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-22 4:23 ` Jonathan Wakely
@ 2015-01-25 10:11 ` François Dumont
2015-01-25 11:30 ` Jonathan Wakely
0 siblings, 1 reply; 10+ messages in thread
From: François Dumont @ 2015-01-25 10:11 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1453 bytes --]
Sorry, I hadn't notice the condition to expose the new methods. It was
hidden within the _Rb_tree type that I hadn't check (and I do not often
check the Standard directly for my limited patches).
On my side I am surprised you didn't reuse your code to detect member
types. I am also surprised that it is not using enable_if, IMHO it makes
the code clearer. Here is a proposal to use both extended to the debug
mode too.
François
On 22/01/2015 03:07, Jonathan Wakely wrote:
> On 21/01/15 23:30 +0100, François Dumont wrote:
>> +#if __cplusplus > 201103L
>> + template<typename _Kt>
>> + std::pair<iterator, iterator>
>> + equal_range(const _Kt& __x)
>> + {
>> + std::pair<_Base_iterator, _Base_iterator> __res =
>> + _Base::equal_range(__x);
>> + return std::make_pair(iterator(__res.first, this),
>> + iterator(__res.second, this));
>> + }
>
> BTW, this is C++14 code, what's wrong with:
>
> template<typename _Kt>
> std::pair<const_iterator, const_iterator>
> equal_range(const _Kt& __x) const
> {
> auto __res = _Base::equal_range(__x);
> return { iterator(__res.first, this), iterator(__res.second,
> this) };
> }
>
> Or even:
>
> template<typename _Kt>
> std::pair<const_iterator, const_iterator>
> equal_range(const _Kt& __x) const
> {
> auto __res = _Base::equal_range(__x);
> return { { __res.first, this }, {__res.second, this} };
> }
>
[-- Attachment #2: asso_cont.patch --]
[-- Type: text/x-patch, Size: 16682 bytes --]
Index: include/bits/stl_tree.h
===================================================================
--- include/bits/stl_tree.h (revision 220078)
+++ include/bits/stl_tree.h (working copy)
@@ -342,6 +342,9 @@
_Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z,
_Rb_tree_node_base& __header) throw ();
+#if __cplusplus > 201103L
+ _GLIBCXX_HAS_NESTED_TYPE(is_transparent)
+#endif
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc = allocator<_Val> >
@@ -1119,14 +1122,6 @@
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); }
@@ -1155,9 +1150,8 @@
return _S_iter(__y);
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- iterator
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
_M_find_tr(const _Kt& __k)
{
auto& __cmp = _M_impl._M_key_compare;
@@ -1166,9 +1160,8 @@
? end() : __j;
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- const_iterator
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
_M_find_tr(const _Kt& __k) const
{
auto& __cmp = _M_impl._M_key_compare;
@@ -1177,9 +1170,8 @@
? end() : __j;
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- size_type
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, size_type>
_M_count_tr(const _Kt& __k) const
{
auto __p = _M_equal_range_tr(__k);
@@ -1186,9 +1178,8 @@
return std::distance(__p.first, __p.second);
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- iterator
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
_M_lower_bound_tr(const _Kt& __k)
{
auto& __cmp = _M_impl._M_key_compare;
@@ -1195,9 +1186,8 @@
return _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- const_iterator
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
_M_lower_bound_tr(const _Kt& __k) const
{
auto& __cmp = _M_impl._M_key_compare;
@@ -1204,9 +1194,8 @@
return _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- iterator
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
_M_upper_bound_tr(const _Kt& __k)
{
auto& __cmp = _M_impl._M_key_compare;
@@ -1213,9 +1202,8 @@
return _S_upper_bound_tr(__cmp, _M_begin(), _M_end(), __k);
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- const_iterator
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
_M_upper_bound_tr(const _Kt& __k) const
{
auto& __cmp = _M_impl._M_key_compare;
@@ -1222,9 +1210,9 @@
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>
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ pair<iterator, iterator>>
_M_equal_range_tr(const _Kt& __k)
{
auto __low = _M_lower_bound_tr(__k);
@@ -1235,9 +1223,9 @@
return { __low, __high };
}
- template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
- pair<const_iterator, const_iterator>
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ pair<const_iterator, const_iterator>>
_M_equal_range_tr(const _Kt& __k) const
{
auto __low = _M_lower_bound_tr(__k);
Index: include/debug/map.h
===================================================================
--- include/debug/map.h (revision 220078)
+++ include/debug/map.h (working copy)
@@ -412,10 +412,24 @@
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+#endif
+
const_iterator
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -422,18 +436,46 @@
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ lower_bound(const _Kt& __x)
+ { return iterator(_Base::lower_bound(__x), this); }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ lower_bound(const _Kt& __x) const
+ { return const_iterator(_Base::lower_bound(__x), this); }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ upper_bound(const _Kt& __x)
+ { return iterator(_Base::upper_bound(__x), this); }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ upper_bound(const _Kt& __x) const
+ { return const_iterator(_Base::upper_bound(__x), this); }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -443,6 +485,17 @@
iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<iterator, iterator>>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -452,6 +505,17 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<const_iterator, const_iterator>>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/multimap.h
===================================================================
--- include/debug/multimap.h (revision 220078)
+++ include/debug/multimap.h (working copy)
@@ -393,10 +393,24 @@
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+#endif
+
const_iterator
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -403,18 +417,46 @@
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ lower_bound(const _Kt& __x)
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ lower_bound(const _Kt& __x) const
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ upper_bound(const _Kt& __x)
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ upper_bound(const _Kt& __x) const
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -424,6 +466,17 @@
iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<iterator, iterator>>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -433,6 +486,17 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<const_iterator, const_iterator>>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/set.h
===================================================================
--- include/debug/set.h (revision 220078)
+++ include/debug/set.h (working copy)
@@ -393,6 +393,18 @@
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -405,6 +417,18 @@
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ lower_bound(const _Kt& __x)
+ { return { _Base::lower_bound(__x), this }; }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ lower_bound(const _Kt& __x) const
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
@@ -415,6 +439,18 @@
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ upper_bound(const _Kt& __x)
+ { return { _Base::upper_bound(__x), this }; }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ upper_bound(const _Kt& __x) const
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -429,12 +465,32 @@
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
- std::pair<_Base_iterator, _Base_iterator> __res =
+ std::pair<_Base_const_iterator, _Base_const_iterator> __res =
_Base::equal_range(__x);
return std::make_pair(const_iterator(__res.first, this),
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<iterator, iterator>>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<const_iterator, const_iterator>>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/multiset.h
===================================================================
--- include/debug/multiset.h (revision 220078)
+++ include/debug/multiset.h (working copy)
@@ -386,6 +386,18 @@
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -398,6 +410,18 @@
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ lower_bound(const _Kt& __x)
+ { return { _Base::lower_bound(__x), this }; }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ lower_bound(const _Kt& __x) const
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
@@ -408,6 +432,18 @@
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
+ upper_bound(const _Kt& __x)
+ { return { _Base::upper_bound(__x), this }; }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value, const_iterator>
+ upper_bound(const _Kt& __x) const
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -428,6 +464,26 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<iterator, iterator>>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+
+ template<typename _Kt>
+ enable_if_t<__has_is_transparent<_Compare>::value,
+ std::pair<const_iterator, const_iterator>>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-25 10:11 ` François Dumont
@ 2015-01-25 11:30 ` Jonathan Wakely
2015-01-25 12:34 ` Jonathan Wakely
2015-01-26 12:11 ` Jonathan Wakely
0 siblings, 2 replies; 10+ messages in thread
From: Jonathan Wakely @ 2015-01-25 11:30 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 24/01/15 23:03 +0100, François Dumont wrote:
>Sorry, I hadn't notice the condition to expose the new methods. It was
>hidden within the _Rb_tree type that I hadn't check (and I do not
>often check the Standard directly for my limited patches).
>
>On my side I am surprised you didn't reuse your code to detect member
That adds another class template to the global namespace. I did that
initially, but (because I forgot about Debug + Profile modes) decided
against defining a new global type that is only needed in one place.
(N.B. _GLIBCXX_HAS_NESTED_TYPE is not mine, I only modified it
recently to use __void_t when I added that. Personally I find directly
using void_t is simpler than defining a new type using void_t and then
using that. I expect that to be the idiomatic solution in C++17 when
std::void_t is added.
>types. I am also surprised that it is not using enable_if, IMHO it
>makes the code clearer.
It doesn't work though.
>@@ -1155,9 +1150,8 @@
> return _S_iter(__y);
> }
>
>- template<typename _Kt,
>- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
>- iterator
>+ template<typename _Kt>
>+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
> _M_find_tr(const _Kt& __k)
This doesn't work.
Consider:
#include <set>
struct I
{
int i;
operator int() const { return i; }
};
int main()
{
std::set<int> s;
I i = { };
s.find(i);
}
(I will add something like this to the testsuite.)
This program is valid according to any C++ standard, but fails to
compile with your patch applied because overload resolution
instantiates std::_Rb_tree<>::_M_find_tr<I> which instantiates
enable_if<false, iterator>::type, which is an error. SFINAE does not
apply, because the invalid type enable_if<false, iterator>::type is
not found during *substitution*. It's just invalid, so when _Compare
is not transparent, instantiating the function template is simply an
error.
Observe that my __is_transparent alias template takes two template
arguments, so that it depends on the template parameter of the
function, not only on _Compare. That means whether if the type is
invalid that will be found during template argument substitution, so
SFINAE applies.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-25 11:30 ` Jonathan Wakely
@ 2015-01-25 12:34 ` Jonathan Wakely
2015-01-26 12:11 ` Jonathan Wakely
1 sibling, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2015-01-25 12:34 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 24/01/15 22:46 +0000, Jonathan Wakely wrote:
>Observe that my __is_transparent alias template takes two template
>arguments, so that it depends on the template parameter of the
>function, not only on _Compare. That means whether if the type is
s/whether //
>invalid that will be found during template argument substitution, so
>SFINAE applies.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-25 11:30 ` Jonathan Wakely
2015-01-25 12:34 ` Jonathan Wakely
@ 2015-01-26 12:11 ` Jonathan Wakely
2015-01-26 22:16 ` François Dumont
1 sibling, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2015-01-26 12:11 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 850 bytes --]
On 24/01/15 22:46 +0000, Jonathan Wakely wrote:
>On 24/01/15 23:03 +0100, François Dumont wrote:
>>types. I am also surprised that it is not using enable_if, IMHO it
>>makes the code clearer.
>
>It doesn't work though.
>
>>@@ -1155,9 +1150,8 @@
>> return _S_iter(__y);
>> }
>>
>>- template<typename _Kt,
>>- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
>>- iterator
>>+ template<typename _Kt>
>>+ enable_if_t<__has_is_transparent<_Compare>::value, iterator>
>> _M_find_tr(const _Kt& __k)
>
>This doesn't work.
>
>Consider:
>
> #include <set>
>
> struct I
> {
> int i;
> operator int() const { return i; }
> };
>
> int main()
> {
> std::set<int> s;
> I i = { };
> s.find(i);
> }
>
>(I will add something like this to the testsuite.)
Done with this patch, tested x86_64-linux and committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 1021 bytes --]
commit ba331e783334feb20f30f1b92a93d8c9d8f895be
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Jan 26 10:43:16 2015 +0000
* testsuite/23_containers/set/operations/2.cc: Add test for
non-transparent comparison function.
diff --git a/libstdc++-v3/testsuite/23_containers/set/operations/2.cc b/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
index 752bc7d..84ddd1f 100644
--- a/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/operations/2.cc
@@ -128,6 +128,22 @@ test05()
VERIFY( Cmp::count == 0);
}
+void
+test06()
+{
+ // https://gcc.gnu.org/ml/libstdc++/2015-01/msg00176.html
+ // Verify the new function template overloads do not cause problems
+ // when the comparison function is not transparent.
+ struct I
+ {
+ int i;
+ operator int() const { return i; }
+ };
+
+ std::set<int> s;
+ I i = { };
+ s.find(i);
+}
int
main()
@@ -137,4 +153,5 @@ main()
test03();
test04();
test05();
+ test06();
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers.
2015-01-26 12:11 ` Jonathan Wakely
@ 2015-01-26 22:16 ` François Dumont
0 siblings, 0 replies; 10+ messages in thread
From: François Dumont @ 2015-01-26 22:16 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 3221 bytes --]
Hi
Thanks a lot for those explanations, very educative. I was indeed
wondering what was the additional template parameter for.
So here is a new attempt. While moving __is_transparent to std
namespace I renamed to __has_is_transparent to not conflict with
existing __is_transparent. I agree that it is another non-standard type
in the std namespace but at the same time should'nt the whole content of
stl_tree.h be in __gnu_cxx rather ? This is perhaps not a reason to make
situation worst so tell me if you want me to move it to std::__detail
namespace ?
At the beginning I wanted to make something like in bits/map.h to
not have to replicate the __is_transparent stuff. But I didn't found any
way to do such a thing.
2015-01-22 François Dumont <fdumont@gcc.gnu.org>
* include/bits/stl_tree.h (_Rb_tree<>::__is_transparent<>): Move to
outer
scope and rename in ...
(std::__hash_is_transparent<>): ... this.
* include/debug/stl_map.h (map::find<>,
map::lower_bound<>, map::upper_bound<>, map::equal_range<>): New
member function templates to perform heterogeneous lookup.
* include/debug/stl_multimap.h (multimap::find<>,
multimap::lower_bound<>, multimap::upper_bound<>,
multimap::equal_range<>): Likewise.
* include/debug/stl_multiset.h (multiset::find<>,
multiset::lower_bound<>, multiset::upper_bound<>,
multiset::equal_range<>): Likewise.
* include/debug/stl_set.h (set::find<>,
set::lower_bound<>, set::upper_bound<>, set::equal_range<>): Likewise.
* include/profile/stl_map.h (map::find<>, map::count<>,
map::lower_bound<>, map::upper_bound<>, map::equal_range<>): Likewise.
* include/profile/stl_multimap.h (multimap::find<>, multimap::cout<>,
multimap::lower_bound<>, multimap::upper_bound<>,
multimap::equal_range<>): Likewise.
* include/profile/stl_multiset.h (multiset::find<>, multiset::count<>,
multiset::lower_bound<>, multiset::upper_bound<>,
multiset::equal_range<>): Likewise.
* include/profile/stl_set.h (set::find<>, set::count<>,
set::lower_bound<>, set::upper_bound<>, set::equal_range<>): Likewise.
Tested under Linux x86_64 normal, debug and profile modes.
François
On 26/01/2015 12:19, Jonathan Wakely wrote:
> On 24/01/15 22:46 +0000, Jonathan Wakely wrote:
>> On 24/01/15 23:03 +0100, François Dumont wrote:
>>> types. I am also surprised that it is not using enable_if, IMHO it
>>> makes the code clearer.
>>
>> It doesn't work though.
>>
>>> @@ -1155,9 +1150,8 @@
>>> return _S_iter(__y);
>>> }
>>>
>>> - template<typename _Kt,
>>> - typename _Req = typename __is_transparent<_Compare,
>>> _Kt>::type>
>>> - iterator
>>> + template<typename _Kt>
>>> + enable_if_t<__has_is_transparent<_Compare>::value, iterator>
>>> _M_find_tr(const _Kt& __k)
>>
>> This doesn't work.
>>
>> Consider:
>>
>> #include <set>
>>
>> struct I
>> {
>> int i;
>> operator int() const { return i; }
>> };
>>
>> int main()
>> {
>> std::set<int> s;
>> I i = { };
>> s.find(i);
>> }
>>
>> (I will add something like this to the testsuite.)
>
> Done with this patch, tested x86_64-linux and committed to trunk.
>
[-- Attachment #2: heterogeneous_lookup.patch --]
[-- Type: text/x-patch, Size: 34379 bytes --]
Index: include/bits/stl_tree.h
===================================================================
--- include/bits/stl_tree.h (revision 220131)
+++ include/bits/stl_tree.h (working copy)
@@ -342,7 +342,17 @@
_Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z,
_Rb_tree_node_base& __header) throw ();
+#if __cplusplus > 201103L
+ template<typename _Cmp, typename _Kt, typename = __void_t<>>
+ struct __has_is_transparent
+ { };
+ template<typename _Cmp, typename _Kt>
+ struct __has_is_transparent<_Cmp, _Kt,
+ __void_t<typename _Cmp::is_transparent>>
+ { typedef void type; };
+#endif
+
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc = allocator<_Val> >
class _Rb_tree
@@ -1119,14 +1129,6 @@
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); }
@@ -1156,7 +1158,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
iterator
_M_find_tr(const _Kt& __k)
{
@@ -1167,7 +1170,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
const_iterator
_M_find_tr(const _Kt& __k) const
{
@@ -1178,7 +1182,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
size_type
_M_count_tr(const _Kt& __k) const
{
@@ -1187,7 +1192,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
iterator
_M_lower_bound_tr(const _Kt& __k)
{
@@ -1196,7 +1202,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
const_iterator
_M_lower_bound_tr(const _Kt& __k) const
{
@@ -1205,7 +1212,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
iterator
_M_upper_bound_tr(const _Kt& __k)
{
@@ -1214,7 +1222,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
const_iterator
_M_upper_bound_tr(const _Kt& __k) const
{
@@ -1223,7 +1232,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
pair<iterator, iterator>
_M_equal_range_tr(const _Kt& __k)
{
@@ -1236,7 +1246,8 @@
}
template<typename _Kt,
- typename _Req = typename __is_transparent<_Compare, _Kt>::type>
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
pair<const_iterator, const_iterator>
_M_equal_range_tr(const _Kt& __k) const
{
Index: include/debug/map.h
===================================================================
--- include/debug/map.h (revision 220131)
+++ include/debug/map.h (working copy)
@@ -412,10 +412,28 @@
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+#endif
+
const_iterator
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -422,18 +440,54 @@
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -443,6 +497,18 @@
iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -452,6 +518,18 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/multimap.h
===================================================================
--- include/debug/multimap.h (revision 220131)
+++ include/debug/multimap.h (working copy)
@@ -393,10 +393,28 @@
find(const key_type& __x)
{ return iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+#endif
+
const_iterator
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -403,18 +421,54 @@
lower_bound(const key_type& __x)
{ return iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -424,6 +478,18 @@
iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -433,6 +499,18 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/set.h
===================================================================
--- include/debug/set.h (revision 220131)
+++ include/debug/set.h (working copy)
@@ -393,6 +393,22 @@
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -405,6 +421,22 @@
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return { _Base::lower_bound(__x), this }; }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
@@ -415,6 +447,22 @@
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return { _Base::upper_bound(__x), this }; }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -429,12 +477,34 @@
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
- std::pair<_Base_iterator, _Base_iterator> __res =
+ std::pair<_Base_const_iterator, _Base_const_iterator> __res =
_Base::equal_range(__x);
return std::make_pair(const_iterator(__res.first, this),
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/debug/multiset.h
===================================================================
--- include/debug/multiset.h (revision 220131)
+++ include/debug/multiset.h (working copy)
@@ -386,6 +386,22 @@
find(const key_type& __x) const
{ return const_iterator(_Base::find(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ { return { _Base::find(__x), this }; }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ { return { _Base::find(__x), this }; }
+#endif
+
using _Base::count;
iterator
@@ -398,6 +414,22 @@
lower_bound(const key_type& __x) const
{ return const_iterator(_Base::lower_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ { return { _Base::lower_bound(__x), this }; }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ { return { _Base::lower_bound(__x), this }; }
+#endif
+
iterator
upper_bound(const key_type& __x)
{ return iterator(_Base::upper_bound(__x), this); }
@@ -408,6 +440,22 @@
upper_bound(const key_type& __x) const
{ return const_iterator(_Base::upper_bound(__x), this); }
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ { return { _Base::upper_bound(__x), this }; }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ { return { _Base::upper_bound(__x), this }; }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -428,6 +476,28 @@
const_iterator(__res.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/profile/map.h
===================================================================
--- include/profile/map.h (revision 220131)
+++ include/profile/map.h (working copy)
@@ -429,6 +429,18 @@
return iterator(_Base::find(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+#endif
+
const_iterator
find(const key_type& __x) const
{
@@ -436,6 +448,18 @@
return const_iterator(_Base::find(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+#endif
+
size_type
count(const key_type& __x) const
{
@@ -443,6 +467,18 @@
return _Base::count(__x);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ size_type
+ count(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return _Base::count(__x);
+ }
+#endif
+
iterator
lower_bound(const key_type& __x)
{
@@ -451,6 +487,19 @@
return iterator(_Base::lower_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{
@@ -459,6 +508,19 @@
return const_iterator(_Base::lower_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+#endif
+
iterator
upper_bound(const key_type& __x)
{
@@ -467,6 +529,19 @@
return iterator(_Base::upper_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{
@@ -475,6 +550,19 @@
return const_iterator(_Base::upper_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -485,6 +573,19 @@
iterator(__base_ret.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -495,6 +596,19 @@
const_iterator(__base_ret.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/profile/multimap.h
===================================================================
--- include/profile/multimap.h (revision 220131)
+++ include/profile/multimap.h (working copy)
@@ -388,6 +388,18 @@
return iterator(_Base::find(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+#endif
+
const_iterator
find(const key_type& __x) const
{
@@ -395,6 +407,18 @@
return const_iterator(_Base::find(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+#endif
+
size_type
count(const key_type& __x) const
{
@@ -402,6 +426,18 @@
return _Base::count(__x);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ size_type
+ count(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return _Base::count(__x);
+ }
+#endif
+
iterator
lower_bound(const key_type& __x)
{
@@ -410,6 +446,19 @@
return iterator(_Base::lower_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+#endif
+
const_iterator
lower_bound(const key_type& __x) const
{
@@ -418,6 +467,19 @@
return const_iterator(_Base::lower_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+#endif
+
iterator
upper_bound(const key_type& __x)
{
@@ -426,6 +488,19 @@
return iterator(_Base::upper_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+#endif
+
const_iterator
upper_bound(const key_type& __x) const
{
@@ -434,6 +509,19 @@
return const_iterator(_Base::upper_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -444,6 +532,19 @@
iterator(__base_ret.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
std::pair<const_iterator,const_iterator>
equal_range(const key_type& __x) const
{
@@ -454,6 +555,19 @@
const_iterator(__base_ret.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/profile/multiset.h
===================================================================
--- include/profile/multiset.h (revision 220131)
+++ include/profile/multiset.h (working copy)
@@ -379,6 +379,18 @@
return _Base::count(__x);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ size_type
+ count(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return _Base::count(__x);
+ }
+#endif
+
// multiset operations:
iterator
find(const key_type& __x)
@@ -396,6 +408,28 @@
return const_iterator(_Base::find(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+#endif
+
iterator
lower_bound(const key_type& __x)
{
@@ -413,6 +447,30 @@
return const_iterator(_Base::lower_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+#endif
+
iterator
upper_bound(const key_type& __x)
{
@@ -431,6 +489,30 @@
return const_iterator(_Base::upper_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+#endif
+
std::pair<iterator,iterator>
equal_range(const key_type& __x)
{
@@ -453,6 +535,30 @@
const_iterator(__base_ret.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
Index: include/profile/set.h
===================================================================
--- include/profile/set.h (revision 220131)
+++ include/profile/set.h (working copy)
@@ -369,6 +369,18 @@
return _Base::count(__x);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ size_type
+ count(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return _Base::count(__x);
+ }
+#endif
+
// set operations:
iterator
find(const key_type& __x)
@@ -384,6 +396,28 @@
return const_iterator(_Base::find(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ find(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ find(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ return { _Base::find(__x), this };
+ }
+#endif
+
iterator
lower_bound(const key_type& __x)
{
@@ -400,6 +434,30 @@
return const_iterator(_Base::lower_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ lower_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ lower_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::lower_bound(__x), this };
+ }
+#endif
+
iterator
upper_bound(const key_type& __x)
{
@@ -416,6 +474,30 @@
return const_iterator(_Base::upper_bound(__x), this);
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ iterator
+ upper_bound(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ const_iterator
+ upper_bound(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ __profcxx_map2umap_invalidate(this->_M_map2umap_info);
+ return { _Base::upper_bound(__x), this };
+ }
+#endif
+
std::pair<iterator, iterator>
equal_range(const key_type& __x)
{
@@ -436,6 +518,30 @@
const_iterator(__base_ret.second, this));
}
+#if __cplusplus > 201103L
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<iterator, iterator>
+ equal_range(const _Kt& __x)
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+
+ template<typename _Kt,
+ typename _Req =
+ typename __has_is_transparent<_Compare, _Kt>::type>
+ std::pair<const_iterator, const_iterator>
+ equal_range(const _Kt& __x) const
+ {
+ __profcxx_map2umap_find(this->_M_map2umap_info, this->size());
+ auto __res = _Base::equal_range(__x);
+ return { { __res.first, this }, { __res.second, this } };
+ }
+#endif
+
_Base&
_M_base() _GLIBCXX_NOEXCEPT { return *this; }
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2015-01-26 21:27 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-19 17:43 [patch] [C++14] Implement N3657: heterogeneous lookup in associative containers Jonathan Wakely
2015-01-20 12:08 ` Jonathan Wakely
2015-01-21 23:03 ` François Dumont
2015-01-22 4:10 ` Jonathan Wakely
2015-01-22 4:23 ` Jonathan Wakely
2015-01-25 10:11 ` François Dumont
2015-01-25 11:30 ` Jonathan Wakely
2015-01-25 12:34 ` Jonathan Wakely
2015-01-26 12:11 ` Jonathan Wakely
2015-01-26 22:16 ` François Dumont
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).