Skip to content

Commit e5ec94a

Browse files
rarutyunldionne
authored andcommitted
[libc++] Implement P0919R3: heterogenous lookup for unordered containers
Implement heterogenous lookup for unordered containers, including the refinement from P1690R1. Differential Revision: https://reviews.llvm.org/D87171
1 parent 37c4ac8 commit e5ec94a

35 files changed

+2015
-59
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ Status
206206
------------------------------------------------- -----------------
207207
``__cpp_lib_erase_if`` ``202002L``
208208
------------------------------------------------- -----------------
209-
``__cpp_lib_generic_unordered_lookup`` *unimplemented*
209+
``__cpp_lib_generic_unordered_lookup`` ``201811L``
210210
------------------------------------------------- -----------------
211211
``__cpp_lib_interpolate`` ``201902L``
212212
------------------------------------------------- -----------------

libcxx/include/unordered_map

Lines changed: 156 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,22 @@ public:
173173
174174
iterator find(const key_type& k);
175175
const_iterator find(const key_type& k) const;
176+
template<typename K>
177+
iterator find(const K& x); // C++20
178+
template<typename K>
179+
const_iterator find(const K& x) const; // C++20
176180
size_type count(const key_type& k) const;
181+
template<typename K>
182+
size_type count(const K& k) const; // C++20
177183
bool contains(const key_type& k) const; // C++20
184+
template<typename K>
185+
bool contains(const K& k) const; // C++20
178186
pair<iterator, iterator> equal_range(const key_type& k);
179187
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
188+
template<typename K>
189+
pair<iterator, iterator> equal_range(const K& k); // C++20
190+
template<typename K>
191+
pair<const_iterator, const_iterator> equal_range(const K& k) const; // C++20
180192
181193
mapped_type& operator[](const key_type& k);
182194
mapped_type& operator[](key_type&& k);
@@ -355,10 +367,22 @@ public:
355367
356368
iterator find(const key_type& k);
357369
const_iterator find(const key_type& k) const;
370+
template<typename K>
371+
iterator find(const K& x); // C++20
372+
template<typename K>
373+
const_iterator find(const K& x) const; // C++20
358374
size_type count(const key_type& k) const;
375+
template<typename K>
376+
size_type count(const K& k) const; // C++20
359377
bool contains(const key_type& k) const; // C++20
378+
template<typename K>
379+
bool contains(const K& k) const; // C++20
360380
pair<iterator, iterator> equal_range(const key_type& k);
361381
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
382+
template<typename K>
383+
pair<iterator, iterator> equal_range(const K& k); // C++20
384+
template<typename K>
385+
pair<const_iterator, const_iterator> equal_range(const K& k) const; // C++20
362386
363387
size_type bucket_count() const noexcept;
364388
size_type max_bucket_count() const noexcept;
@@ -423,7 +447,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc>
423447

424448
_LIBCPP_BEGIN_NAMESPACE_STD
425449

426-
template <class _Key, class _Cp, class _Hash,
450+
template <class _Key, class _Cp, class _Hash, class _Pred,
427451
bool = is_empty<_Hash>::value && !__libcpp_is_final<_Hash>::value>
428452
class __unordered_map_hasher
429453
: private _Hash
@@ -445,6 +469,12 @@ public:
445469
_LIBCPP_INLINE_VISIBILITY
446470
size_t operator()(const _Key& __x) const
447471
{return static_cast<const _Hash&>(*this)(__x);}
472+
#if _LIBCPP_STD_VER > 17
473+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
474+
_LIBCPP_INLINE_VISIBILITY
475+
size_t operator()(const _K2& __x) const
476+
{return static_cast<const _Hash&>(*this)(__x);}
477+
#endif
448478
void swap(__unordered_map_hasher&__y)
449479
_NOEXCEPT_(__is_nothrow_swappable<_Hash>::value)
450480
{
@@ -453,8 +483,8 @@ public:
453483
}
454484
};
455485

456-
template <class _Key, class _Cp, class _Hash>
457-
class __unordered_map_hasher<_Key, _Cp, _Hash, false>
486+
template <class _Key, class _Cp, class _Hash, class _Pred>
487+
class __unordered_map_hasher<_Key, _Cp, _Hash, _Pred, false>
458488
{
459489
_Hash __hash_;
460490
public:
@@ -474,6 +504,12 @@ public:
474504
_LIBCPP_INLINE_VISIBILITY
475505
size_t operator()(const _Key& __x) const
476506
{return __hash_(__x);}
507+
#if _LIBCPP_STD_VER > 17
508+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
509+
_LIBCPP_INLINE_VISIBILITY
510+
size_t operator()(const _K2& __x) const
511+
{return __hash_(__x);}
512+
#endif
477513
void swap(__unordered_map_hasher&__y)
478514
_NOEXCEPT_(__is_nothrow_swappable<_Hash>::value)
479515
{
@@ -482,17 +518,17 @@ public:
482518
}
483519
};
484520

485-
template <class _Key, class _Cp, class _Hash, bool __b>
521+
template <class _Key, class _Cp, class _Hash, class _Pred, bool __b>
486522
inline _LIBCPP_INLINE_VISIBILITY
487523
void
488-
swap(__unordered_map_hasher<_Key, _Cp, _Hash, __b>& __x,
489-
__unordered_map_hasher<_Key, _Cp, _Hash, __b>& __y)
524+
swap(__unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __x,
525+
__unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __y)
490526
_NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
491527
{
492528
__x.swap(__y);
493529
}
494530

495-
template <class _Key, class _Cp, class _Pred,
531+
template <class _Key, class _Cp, class _Pred, class _Hash,
496532
bool = is_empty<_Pred>::value && !__libcpp_is_final<_Pred>::value>
497533
class __unordered_map_equal
498534
: private _Pred
@@ -517,6 +553,24 @@ public:
517553
_LIBCPP_INLINE_VISIBILITY
518554
bool operator()(const _Key& __x, const _Cp& __y) const
519555
{return static_cast<const _Pred&>(*this)(__x, __y.__get_value().first);}
556+
#if _LIBCPP_STD_VER > 17
557+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
558+
_LIBCPP_INLINE_VISIBILITY
559+
bool operator()(const _Cp& __x, const _K2& __y) const
560+
{return static_cast<const _Pred&>(*this)(__x.__get_value().first, __y);}
561+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
562+
_LIBCPP_INLINE_VISIBILITY
563+
bool operator()(const _K2& __x, const _Cp& __y) const
564+
{return static_cast<const _Pred&>(*this)(__x, __y.__get_value().first);}
565+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
566+
_LIBCPP_INLINE_VISIBILITY
567+
bool operator()(const _Key& __x, const _K2& __y) const
568+
{return static_cast<const _Pred&>(*this)(__x, __y);}
569+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
570+
_LIBCPP_INLINE_VISIBILITY
571+
bool operator()(const _K2& __x, const _Key& __y) const
572+
{return static_cast<const _Pred&>(*this)(__x, __y);}
573+
#endif
520574
void swap(__unordered_map_equal&__y)
521575
_NOEXCEPT_(__is_nothrow_swappable<_Pred>::value)
522576
{
@@ -525,8 +579,8 @@ public:
525579
}
526580
};
527581

528-
template <class _Key, class _Cp, class _Pred>
529-
class __unordered_map_equal<_Key, _Cp, _Pred, false>
582+
template <class _Key, class _Cp, class _Pred, class _Hash>
583+
class __unordered_map_equal<_Key, _Cp, _Pred, _Hash, false>
530584
{
531585
_Pred __pred_;
532586
public:
@@ -549,6 +603,24 @@ public:
549603
_LIBCPP_INLINE_VISIBILITY
550604
bool operator()(const _Key& __x, const _Cp& __y) const
551605
{return __pred_(__x, __y.__get_value().first);}
606+
#if _LIBCPP_STD_VER > 17
607+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
608+
_LIBCPP_INLINE_VISIBILITY
609+
bool operator()(const _Cp& __x, const _K2& __y) const
610+
{return __pred_(__x.__get_value().first, __y);}
611+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
612+
_LIBCPP_INLINE_VISIBILITY
613+
bool operator()(const _K2& __x, const _Cp& __y) const
614+
{return __pred_(__x, __y.__get_value().first);}
615+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
616+
_LIBCPP_INLINE_VISIBILITY
617+
bool operator()(const _Key& __x, const _K2& __y) const
618+
{return __pred_(__x, __y);}
619+
template <typename _K2, typename = _EnableIf<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value>>
620+
_LIBCPP_INLINE_VISIBILITY
621+
bool operator()(const _K2& __x, const _Key& __y) const
622+
{return __pred_(__x, __y);}
623+
#endif
552624
void swap(__unordered_map_equal&__y)
553625
_NOEXCEPT_(__is_nothrow_swappable<_Pred>::value)
554626
{
@@ -557,11 +629,11 @@ public:
557629
}
558630
};
559631

560-
template <class _Key, class _Cp, class _Pred, bool __b>
632+
template <class _Key, class _Cp, class _Pred, class _Hash, bool __b>
561633
inline _LIBCPP_INLINE_VISIBILITY
562634
void
563-
swap(__unordered_map_equal<_Key, _Cp, _Pred, __b>& __x,
564-
__unordered_map_equal<_Key, _Cp, _Pred, __b>& __y)
635+
swap(__unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __x,
636+
__unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __y)
565637
_NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
566638
{
567639
__x.swap(__y);
@@ -858,11 +930,11 @@ public:
858930
"Invalid allocator::value_type");
859931

860932
private:
861-
typedef __hash_value_type<key_type, mapped_type> __value_type;
862-
typedef __unordered_map_hasher<key_type, __value_type, hasher> __hasher;
863-
typedef __unordered_map_equal<key_type, __value_type, key_equal> __key_equal;
933+
typedef __hash_value_type<key_type, mapped_type> __value_type;
934+
typedef __unordered_map_hasher<key_type, __value_type, hasher, key_equal> __hasher;
935+
typedef __unordered_map_equal<key_type, __value_type, key_equal, hasher> __key_equal;
864936
typedef typename __rebind_alloc_helper<allocator_traits<allocator_type>,
865-
__value_type>::type __allocator_type;
937+
__value_type>::type __allocator_type;
866938

867939
typedef __hash_table<__value_type, __hasher,
868940
__key_equal, __allocator_type> __table;
@@ -1280,18 +1352,51 @@ public:
12801352
iterator find(const key_type& __k) {return __table_.find(__k);}
12811353
_LIBCPP_INLINE_VISIBILITY
12821354
const_iterator find(const key_type& __k) const {return __table_.find(__k);}
1355+
1356+
#if _LIBCPP_STD_VER > 17
1357+
template <typename _K2>
1358+
_LIBCPP_INLINE_VISIBILITY
1359+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, iterator>
1360+
find(const _K2& __k) {return __table_.find(__k);}
1361+
template <typename _K2>
1362+
_LIBCPP_INLINE_VISIBILITY
1363+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, const_iterator>
1364+
find(const _K2& __k) const {return __table_.find(__k);}
1365+
#endif // _LIBCPP_STD_VER > 17
1366+
12831367
_LIBCPP_INLINE_VISIBILITY
12841368
size_type count(const key_type& __k) const {return __table_.__count_unique(__k);}
1369+
#if _LIBCPP_STD_VER > 17
1370+
template <typename _K2>
1371+
_LIBCPP_INLINE_VISIBILITY
1372+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, size_type>
1373+
count(const _K2& __k) const {return __table_.__count_unique(__k);}
1374+
#endif // _LIBCPP_STD_VER > 17
12851375
#if _LIBCPP_STD_VER > 17
12861376
_LIBCPP_INLINE_VISIBILITY
12871377
bool contains(const key_type& __k) const {return find(__k) != end();}
1378+
1379+
template <typename _K2>
1380+
_LIBCPP_INLINE_VISIBILITY
1381+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, bool>
1382+
contains(const _K2& __k) const {return find(__k) != end();}
12881383
#endif // _LIBCPP_STD_VER > 17
12891384
_LIBCPP_INLINE_VISIBILITY
12901385
pair<iterator, iterator> equal_range(const key_type& __k)
12911386
{return __table_.__equal_range_unique(__k);}
12921387
_LIBCPP_INLINE_VISIBILITY
12931388
pair<const_iterator, const_iterator> equal_range(const key_type& __k) const
12941389
{return __table_.__equal_range_unique(__k);}
1390+
#if _LIBCPP_STD_VER > 17
1391+
template <typename _K2>
1392+
_LIBCPP_INLINE_VISIBILITY
1393+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, pair<iterator, iterator>>
1394+
equal_range(const _K2& __k) {return __table_.__equal_range_unique(__k);}
1395+
template <typename _K2>
1396+
_LIBCPP_INLINE_VISIBILITY
1397+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, pair<const_iterator, const_iterator>>
1398+
equal_range(const _K2& __k) const {return __table_.__equal_range_unique(__k);}
1399+
#endif // _LIBCPP_STD_VER > 17
12951400

12961401
mapped_type& operator[](const key_type& __k);
12971402
#ifndef _LIBCPP_CXX03_LANG
@@ -1762,11 +1867,11 @@ public:
17621867
"Invalid allocator::value_type");
17631868

17641869
private:
1765-
typedef __hash_value_type<key_type, mapped_type> __value_type;
1766-
typedef __unordered_map_hasher<key_type, __value_type, hasher> __hasher;
1767-
typedef __unordered_map_equal<key_type, __value_type, key_equal> __key_equal;
1870+
typedef __hash_value_type<key_type, mapped_type> __value_type;
1871+
typedef __unordered_map_hasher<key_type, __value_type, hasher, key_equal> __hasher;
1872+
typedef __unordered_map_equal<key_type, __value_type, key_equal, hasher> __key_equal;
17681873
typedef typename __rebind_alloc_helper<allocator_traits<allocator_type>,
1769-
__value_type>::type __allocator_type;
1874+
__value_type>::type __allocator_type;
17701875

17711876
typedef __hash_table<__value_type, __hasher,
17721877
__key_equal, __allocator_type> __table;
@@ -2059,18 +2164,49 @@ public:
20592164
iterator find(const key_type& __k) {return __table_.find(__k);}
20602165
_LIBCPP_INLINE_VISIBILITY
20612166
const_iterator find(const key_type& __k) const {return __table_.find(__k);}
2167+
#if _LIBCPP_STD_VER > 17
2168+
template <typename _K2>
2169+
_LIBCPP_INLINE_VISIBILITY
2170+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, iterator>
2171+
find(const _K2& __k) {return __table_.find(__k);}
2172+
template <typename _K2>
2173+
_LIBCPP_INLINE_VISIBILITY
2174+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, const_iterator>
2175+
find(const _K2& __k) const {return __table_.find(__k);}
2176+
#endif // _LIBCPP_STD_VER > 17
20622177
_LIBCPP_INLINE_VISIBILITY
20632178
size_type count(const key_type& __k) const {return __table_.__count_multi(__k);}
2179+
#if _LIBCPP_STD_VER > 17
2180+
template <typename _K2>
2181+
_LIBCPP_INLINE_VISIBILITY
2182+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, size_type>
2183+
count(const _K2& __k) const {return __table_.__count_multi(__k);}
2184+
#endif // _LIBCPP_STD_VER > 17
20642185
#if _LIBCPP_STD_VER > 17
20652186
_LIBCPP_INLINE_VISIBILITY
20662187
bool contains(const key_type& __k) const {return find(__k) != end();}
2188+
2189+
template <typename _K2>
2190+
_LIBCPP_INLINE_VISIBILITY
2191+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, bool>
2192+
contains(const _K2& __k) const {return find(__k) != end();}
20672193
#endif // _LIBCPP_STD_VER > 17
20682194
_LIBCPP_INLINE_VISIBILITY
20692195
pair<iterator, iterator> equal_range(const key_type& __k)
20702196
{return __table_.__equal_range_multi(__k);}
20712197
_LIBCPP_INLINE_VISIBILITY
20722198
pair<const_iterator, const_iterator> equal_range(const key_type& __k) const
20732199
{return __table_.__equal_range_multi(__k);}
2200+
#if _LIBCPP_STD_VER > 17
2201+
template <typename _K2>
2202+
_LIBCPP_INLINE_VISIBILITY
2203+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, pair<iterator, iterator>>
2204+
equal_range(const _K2& __k) {return __table_.__equal_range_multi(__k);}
2205+
template <typename _K2>
2206+
_LIBCPP_INLINE_VISIBILITY
2207+
_EnableIf<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value, pair<const_iterator, const_iterator>>
2208+
equal_range(const _K2& __k) const {return __table_.__equal_range_multi(__k);}
2209+
#endif // _LIBCPP_STD_VER > 17
20742210

20752211
_LIBCPP_INLINE_VISIBILITY
20762212
size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();}

0 commit comments

Comments
 (0)