Index: libcxx/include/unordered_map =================================================================== --- libcxx/include/unordered_map +++ libcxx/include/unordered_map @@ -173,10 +173,22 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; + template + iterator find(const K& x); // C++20 + template + const_iterator find(const K& x) const; // C++20 size_type count(const key_type& k) const; + template + size_type count(const K& k) const; // C++20 bool contains(const key_type& k) const; // C++20 + template + bool contains(const K& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; + template + pair equal_range(const K& k); // C++20 + template + pair equal_range(const K& k) const; // C++20 mapped_type& operator[](const key_type& k); mapped_type& operator[](key_type&& k); @@ -355,10 +367,22 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; + template + iterator find(const K& x); // C++20 + template + const_iterator find(const K& x) const; // C++20 size_type count(const key_type& k) const; + template + size_type count(const K& k) const; // C++20 bool contains(const key_type& k) const; // C++20 + template + bool contains(const K& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; + template + pair equal_range(const K& k); // C++20 + template + pair equal_range(const K& k) const; // C++20 size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; @@ -423,7 +447,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template ::value && !__libcpp_is_final<_Hash>::value> class __unordered_map_hasher : private _Hash @@ -445,6 +469,12 @@ _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return static_cast(*this)(__x);} +#if _LIBCPP_STD_VER > 17 + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value, size_t> operator()(const _K2& __x) const + {return static_cast(*this)(__x);} +#endif void swap(__unordered_map_hasher&__y) _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) { @@ -453,8 +483,8 @@ } }; -template -class __unordered_map_hasher<_Key, _Cp, _Hash, false> +template +class __unordered_map_hasher<_Key, _Cp, _Hash, _Pred, false> { _Hash __hash_; public: @@ -474,6 +504,12 @@ _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return __hash_(__x);} +#if _LIBCPP_STD_VER > 17 + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Hash, _K2>::value && __is_transparent<_Pred, _K2>::value, size_t> operator()(const _K2& __x) const + {return __hash_(__x);} +#endif void swap(__unordered_map_hasher&__y) _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value) { @@ -482,17 +518,17 @@ } }; -template +template inline _LIBCPP_INLINE_VISIBILITY void -swap(__unordered_map_hasher<_Key, _Cp, _Hash, __b>& __x, - __unordered_map_hasher<_Key, _Cp, _Hash, __b>& __y) +swap(__unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __x, + __unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } -template ::value && !__libcpp_is_final<_Pred>::value> class __unordered_map_equal : private _Pred @@ -517,6 +553,24 @@ _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return static_cast(*this)(__x, __y.__get_value().first);} +#if _LIBCPP_STD_VER > 17 + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _Cp& __x, const _K2& __y) const + {return static_cast(*this)(__x.__get_value().first, __y);} + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _K2& __x, const _Cp& __y) const + {return static_cast(*this)(__x, __y.__get_value().first);} + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _Key& __x, const _K2& __y) const + {return static_cast(*this)(__x, __y);} + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _K2& __x, const _Key& __y) const + {return static_cast(*this)(__x, __y);} +#endif void swap(__unordered_map_equal&__y) _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) { @@ -525,8 +579,8 @@ } }; -template -class __unordered_map_equal<_Key, _Cp, _Pred, false> +template +class __unordered_map_equal<_Key, _Cp, _Pred, _Hash, false> { _Pred __pred_; public: @@ -549,6 +603,24 @@ _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return __pred_(__x, __y.__get_value().first);} +#if _LIBCPP_STD_VER > 17 + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _Cp& __x, const _K2& __y) const + {return __pred_(__x.__get_value().first, __y);} + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _K2& __x, const _Cp& __y) const + {return __pred_(__x, __y.__get_value().first);} + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _Key& __x, const _K2& __y) const + {return __pred_(__x, __y);} + template + _LIBCPP_INLINE_VISIBILITY + enable_if_t<__is_transparent<_Pred, _K2>::value && __is_transparent<_Hash, _K2>::value, bool> operator()(const _K2& __x, const _Key& __y) const + {return __pred_(__x, __y);} +#endif void swap(__unordered_map_equal&__y) _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value) { @@ -557,11 +629,11 @@ } }; -template +template inline _LIBCPP_INLINE_VISIBILITY void -swap(__unordered_map_equal<_Key, _Cp, _Pred, __b>& __x, - __unordered_map_equal<_Key, _Cp, _Pred, __b>& __y) +swap(__unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __x, + __unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); @@ -858,11 +930,11 @@ "Invalid allocator::value_type"); private: - typedef __hash_value_type __value_type; - typedef __unordered_map_hasher __hasher; - typedef __unordered_map_equal __key_equal; + typedef __hash_value_type __value_type; + typedef __unordered_map_hasher __hasher; + typedef __unordered_map_equal __key_equal; typedef typename __rebind_alloc_helper, - __value_type>::type __allocator_type; + __value_type>::type __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; @@ -1280,11 +1352,30 @@ iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} + + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + iterator find(const _K2& __k) {return __table_.find(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + const_iterator find(const _K2& __k) const {return __table_.find(__k);} + #endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + size_type count(const _K2& __k) const {return __table_.__count_unique(__k);} + #endif // _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} + + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + bool contains(const _K2& __k) const {return find(__k) != end();} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) @@ -1292,6 +1383,14 @@ _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) {return __table_.__equal_range_unique(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) const {return __table_.__equal_range_unique(__k);} + #endif // _LIBCPP_STD_VER > 17 mapped_type& operator[](const key_type& __k); #ifndef _LIBCPP_CXX03_LANG @@ -1762,11 +1861,11 @@ "Invalid allocator::value_type"); private: - typedef __hash_value_type __value_type; - typedef __unordered_map_hasher __hasher; - typedef __unordered_map_equal __key_equal; + typedef __hash_value_type __value_type; + typedef __unordered_map_hasher __hasher; + typedef __unordered_map_equal __key_equal; typedef typename __rebind_alloc_helper, - __value_type>::type __allocator_type; + __value_type>::type __allocator_type; typedef __hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table; @@ -2059,11 +2158,28 @@ iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + iterator find(const _K2& __k) {return __table_.find(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + const_iterator find(const _K2& __k) const {return __table_.find(__k);} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + size_type count(const _K2& __k) const {return __table_.__count_multi(__k);} + #endif // _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} + + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + bool contains(const _K2& __k) const {return find(__k) != end();} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) @@ -2071,6 +2187,14 @@ _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) {return __table_.__equal_range_multi(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) const {return __table_.__equal_range_multi(__k);} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} Index: libcxx/include/unordered_set =================================================================== --- libcxx/include/unordered_set +++ libcxx/include/unordered_set @@ -145,10 +145,22 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; + template + iterator find(const K& x); // C++20 + template + const_iterator find(const K& x) const; // C++20 size_type count(const key_type& k) const; + template + size_type count(const K& k) const; // C++20 bool contains(const key_type& k) const; // C++20 + template + bool contains(const K& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; + template + pair equal_range(const K& k); // C++20 + template + pair equal_range(const K& k) const; // C++20 size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; @@ -310,10 +322,22 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; + template + iterator find(const K& x); // C++20 + template + const_iterator find(const K& x) const; // C++20 size_type count(const key_type& k) const; + template + size_type count(const K& k) const; // C++20 bool contains(const key_type& k) const; // C++20 + template + bool contains(const K& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; + template + pair equal_range(const K& k); // C++20 + template + pair equal_range(const K& k) const; // C++20 size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; @@ -679,11 +703,28 @@ iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + iterator find(const _K2& __k) {return __table_.find(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + const_iterator find(const _K2& __k) const {return __table_.find(__k);} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + size_type count(const _K2& __k) const {return __table_.__count_unique(__k);} + #endif // _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} + + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + bool contains(const _K2& __k) const {return find(__k) != end();} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) @@ -691,6 +732,14 @@ _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) {return __table_.__equal_range_unique(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) const {return __table_.__equal_range_unique(__k);} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} @@ -1314,11 +1363,28 @@ iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + iterator find(const _K2& __k) {return __table_.find(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + const_iterator find(const _K2& __k) const {return __table_.find(__k);} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + size_type count(const _K2& __k) const {return __table_.__count_multi(__k);} + #endif // _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} + + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + bool contains(const _K2& __k) const {return find(__k) != end();} #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) @@ -1326,6 +1392,14 @@ _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} + #if _LIBCPP_STD_VER > 17 + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) {return __table_.__equal_range_multi(__k);} + template requires __is_transparent::value && __is_transparent::value + _LIBCPP_INLINE_VISIBILITY + pair equal_range(const _K2& __k) const {return __table_.__equal_range_multi(__k);} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} Index: libcxx/test/std/containers/unord/unord.map/contains.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.map/contains.pass.cpp +++ libcxx/test/std/containers/unord/unord.map/contains.pass.cpp @@ -10,6 +10,7 @@ #include #include +#include "test_transparent_unordered.h" // @@ -57,5 +58,89 @@ std::make_pair(3, E{}), std::make_pair(4, E{})); } + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_map > + map_type; + test_transparent_contains(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_map + map_type; + test_transparent_contains(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_map, + std::equal_to<> > + map_type; + test_non_transparent_contains(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_map > + map_type; + test_non_transparent_contains(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_map, + std::equal_to > + map_type; + test_non_transparent_contains(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multimap > + map_type; + test_transparent_contains(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multimap< + Comp2Int, int, transparent_hash_final, transparent_equal_final> + map_type; + test_transparent_contains(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multimap, + std::equal_to<> > + map_type; + test_non_transparent_contains( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multimap > + map_type; + test_non_transparent_contains( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multimap, + std::equal_to > + map_type; + test_non_transparent_contains( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + return 0; } Index: libcxx/test/std/containers/unord/unord.map/count.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.map/count.pass.cpp +++ libcxx/test/std/containers/unord/unord.map/count.pass.cpp @@ -20,6 +20,8 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" +#include int main(int, char**) { @@ -63,5 +65,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_map > + map_type; + test_transparent_count(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_map + map_type; + test_transparent_count(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_map, + std::equal_to<> > + map_type; + test_non_transparent_count(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_map > + map_type; + test_non_transparent_count(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_map, + std::equal_to > + map_type; + test_non_transparent_count(ilist_type{{1, 2}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.map/equal_range_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.map/equal_range_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.map/equal_range_const.pass.cpp @@ -20,6 +20,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -73,5 +74,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_map > + map_type; + test_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_map + map_type; + test_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_map, + std::equal_to<> > + map_type; + test_non_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_map > + map_type; + test_non_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_map, + std::equal_to > + map_type; + test_non_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.map/equal_range_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.map/equal_range_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.map/equal_range_non_const.pass.cpp @@ -20,6 +20,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -73,5 +74,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_map > + map_type; + test_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_map + map_type; + test_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_map, + std::equal_to<> > + map_type; + test_non_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_map > + map_type; + test_non_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_map, + std::equal_to > + map_type; + test_non_transparent_equal_range(ilist_type{{1, 2}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.map/find_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.map/find_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.map/find_const.pass.cpp @@ -20,6 +20,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -69,5 +70,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_map > + map_type; + test_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_map + map_type; + test_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_map, + std::equal_to<> > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_map > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_map, + std::equal_to > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.map/find_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.map/find_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.map/find_non_const.pass.cpp @@ -20,6 +20,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -69,5 +70,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_map > + map_type; + test_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_map + map_type; + test_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_map, + std::equal_to<> > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_map > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_map, + std::equal_to > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multimap/count.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multimap/count.pass.cpp +++ libcxx/test/std/containers/unord/unord.multimap/count.pass.cpp @@ -20,6 +20,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -69,5 +70,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multimap > + map_type; + test_transparent_count(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multimap< + Comp2Int, int, transparent_hash_final, transparent_equal_final> + map_type; + test_transparent_count(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multimap, + std::equal_to<> > + map_type; + test_non_transparent_count(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multimap > + map_type; + test_non_transparent_count(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multimap, + std::equal_to > + map_type; + test_non_transparent_count(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multimap/equal_range_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multimap/equal_range_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multimap/equal_range_const.pass.cpp @@ -21,6 +21,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -102,5 +103,53 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multimap > + map_type; + test_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multimap< + Comp2Int, int, transparent_hash_final, transparent_equal_final> + map_type; + test_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multimap, + std::equal_to<> > + map_type; + test_non_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multimap > + map_type; + test_non_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multimap, + std::equal_to > + map_type; + test_non_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multimap/equal_range_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multimap/equal_range_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multimap/equal_range_non_const.pass.cpp @@ -21,6 +21,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -102,5 +103,53 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_multimap > + map_type; + test_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_multimap + map_type; + test_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_multimap, + std::equal_to<> > + map_type; + test_non_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_multimap > + map_type; + test_non_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_multimap, + std::equal_to > + map_type; + test_non_transparent_equal_range( + ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multimap/find_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multimap/find_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multimap/find_const.pass.cpp @@ -20,6 +20,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -69,5 +70,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multimap > + map_type; + test_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multimap< + Comp2Int, int, transparent_hash_final, transparent_equal_final> + map_type; + test_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multimap, + std::equal_to<> > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multimap > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multimap, + std::equal_to > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multimap/find_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multimap/find_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multimap/find_non_const.pass.cpp @@ -20,6 +20,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -69,5 +70,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list >; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_multimap > + map_type; + test_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_multimap + map_type; + test_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_multimap, + std::equal_to<> > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_multimap > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_multimap, + std::equal_to > + map_type; + test_non_transparent_find(ilist_type{{1, 2}, {1, 3}, {2, 3}}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multiset/count.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multiset/count.pass.cpp +++ libcxx/test/std/containers/unord/unord.multiset/count.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -68,5 +69,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multiset > + set_type; + test_transparent_count(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multiset + set_type; + test_transparent_count(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multiset, + std::equal_to<> > + set_type; + test_non_transparent_count(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multiset > + set_type; + test_non_transparent_count(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multiset, + std::equal_to > + set_type; + test_non_transparent_count(ilist_type{1, 1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multiset/equal_range_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multiset/equal_range_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multiset/equal_range_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -88,5 +89,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multiset > + set_type; + test_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multiset + set_type; + test_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multiset, + std::equal_to<> > + set_type; + test_non_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multiset > + set_type; + test_non_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multiset, + std::equal_to > + set_type; + test_non_transparent_equal_range(ilist_type{1, 1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multiset/equal_range_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multiset/equal_range_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multiset/equal_range_non_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -88,5 +89,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_multiset > + set_type; + test_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_multiset + set_type; + test_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_multiset, + std::equal_to<> > + set_type; + test_non_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_multiset > + set_type; + test_non_transparent_equal_range(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_multiset, + std::equal_to > + set_type; + test_non_transparent_equal_range(ilist_type{1, 1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multiset/find_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multiset/find_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multiset/find_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -66,5 +67,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multiset > + set_type; + test_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multiset + set_type; + test_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multiset, + std::equal_to<> > + set_type; + test_non_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multiset > + set_type; + test_non_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multiset, + std::equal_to > + set_type; + test_non_transparent_find(ilist_type{1, 1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.multiset/find_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.multiset/find_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.multiset/find_non_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -66,5 +67,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_multiset > + set_type; + test_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_multiset + set_type; + test_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_multiset, + std::equal_to<> > + set_type; + test_non_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_multiset > + set_type; + test_non_transparent_find(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_multiset, + std::equal_to > + set_type; + test_non_transparent_find(ilist_type{1, 1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.set/contains.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.set/contains.pass.cpp +++ libcxx/test/std/containers/unord/unord.set/contains.pass.cpp @@ -10,6 +10,7 @@ #include #include +#include "test_transparent_unordered.h" // @@ -39,5 +40,86 @@ test, char>('e', 'a', 'b', 'c', 'd'); } + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_set > + set_type; + test_transparent_contains(ilist_type{1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_set + set_type; + test_transparent_contains(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_set, + std::equal_to<> > + set_type; + test_non_transparent_contains(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_set > + set_type; + test_non_transparent_contains(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_set, + std::equal_to > + set_type; + test_non_transparent_contains(ilist_type{1, 2}); + } + + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_multiset > + set_type; + test_transparent_contains(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_multiset + set_type; + test_transparent_contains(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_multiset, + std::equal_to<> > + set_type; + test_non_transparent_contains(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_multiset > + set_type; + test_non_transparent_contains(ilist_type{1, 1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_multiset, + std::equal_to > + set_type; + test_non_transparent_contains(ilist_type{1, 1, 2}); + } + return 0; } Index: libcxx/test/std/containers/unord/unord.set/count.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.set/count.pass.cpp +++ libcxx/test/std/containers/unord/unord.set/count.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -67,5 +68,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_set > + set_type; + test_transparent_count(ilist_type{1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_set + set_type; + test_transparent_count(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_set, + std::equal_to<> > + set_type; + test_non_transparent_count(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_set > + set_type; + test_non_transparent_count(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_set, + std::equal_to > + set_type; + test_non_transparent_count(ilist_type{1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.set/equal_range_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.set/equal_range_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.set/equal_range_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -79,5 +80,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_set > + set_type; + test_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_set + set_type; + test_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_set, + std::equal_to<> > + set_type; + test_non_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_set > + set_type; + test_non_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_set, + std::equal_to > + set_type; + test_non_transparent_equal_range(ilist_type{1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.set/equal_range_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.set/equal_range_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.set/equal_range_non_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -79,5 +80,46 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_set > + set_type; + test_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_set + set_type; + test_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_set, std::equal_to<> > + set_type; + test_non_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_set > + set_type; + test_non_transparent_equal_range(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_set, + std::equal_to > + set_type; + test_non_transparent_equal_range(ilist_type{1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.set/find_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.set/find_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.set/find_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -65,5 +66,48 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef const std::unordered_set > + set_type; + test_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef const std::unordered_set + set_type; + test_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef const std::unordered_set, + std::equal_to<> > + set_type; + test_non_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef const std::unordered_set > + set_type; + test_non_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef const std::unordered_set, + std::equal_to > + set_type; + test_non_transparent_find(ilist_type{1, 2}); + } +#endif + + return 0; } Index: libcxx/test/std/containers/unord/unord.set/find_non_const.pass.cpp =================================================================== --- libcxx/test/std/containers/unord/unord.set/find_non_const.pass.cpp +++ libcxx/test/std/containers/unord/unord.set/find_non_const.pass.cpp @@ -19,6 +19,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_transparent_unordered.h" int main(int, char**) { @@ -65,5 +66,46 @@ } #endif - return 0; +#if TEST_STD_VER > 17 + using ilist_type = std::initializer_list; + { + // Make sure conversions don't happen for transparent non-final hasher and key_equal + typedef std::unordered_set > + set_type; + test_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions don't happen for transparent final hasher and key_equal + typedef std::unordered_set + set_type; + test_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent hasher + typedef std::unordered_set, std::equal_to<> > + set_type; + test_non_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for non-transparent key_equal + typedef std::unordered_set > + set_type; + test_non_transparent_find(ilist_type{1, 2}); + } + + { + // Make sure conversions do happen for both non-transparent hasher and key_equal + typedef std::unordered_set, + std::equal_to > + set_type; + test_non_transparent_find(ilist_type{1, 2}); + } +#endif + + return 0; } Index: libcxx/test/support/is_transparent.h =================================================================== --- libcxx/test/support/is_transparent.h +++ libcxx/test/support/is_transparent.h @@ -11,6 +11,8 @@ #include "test_macros.h" +#include // for std::equal_to + // testing transparent #if TEST_STD_VER > 11 @@ -79,6 +81,48 @@ bool operator <(const C2Int& rhs, const C2Int& lhs) { return rhs.get() < lhs.get(); } bool operator <(const C2Int& rhs, int lhs) { return rhs.get() < lhs; } -#endif +#endif // TEST_STD_VER > 11 + +#if TEST_STD_VER > 17 + +struct transparent_hash { + template + constexpr std::size_t operator()(T&& t) const + noexcept(noexcept(static_cast(std::forward(t)))) { + return static_cast(std::forward(t)); + } + + using is_transparent = void; +}; + +struct transparent_hash_final final : transparent_hash {}; + +struct transparent_equal_final final : std::equal_to<> {}; + +struct Comp2Int { // convertible from int + Comp2Int() : i_(0) {} + Comp2Int(int i) : i_(i) { ++conversions_count; } + static int get_conversions_count() { return conversions_count; } + static void reset_conversions_count() { conversions_count = 0; } + operator int() const noexcept { return i_; } + +private: + static int conversions_count; + int i_; +}; + +bool operator==(int rhs, const Comp2Int& lhs) { + return rhs == static_cast(lhs); +} +bool operator==(const Comp2Int& rhs, const Comp2Int& lhs) { + return static_cast(lhs) == static_cast(rhs); +} +bool operator==(const Comp2Int& rhs, int lhs) { + return static_cast(rhs) == lhs; +} + +int Comp2Int::conversions_count; + +#endif // TEST_STD_VER > 17 #endif // TRANSPARENT_H Index: libcxx/test/support/test_transparent_unordered.h =================================================================== --- /dev/null +++ libcxx/test/support/test_transparent_unordered.h @@ -0,0 +1,130 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_TRANSPARENT_UNORDERED_H +#define TEST_TRANSPARENT_UNORDERED_H + +#include "test_macros.h" +#include "is_transparent.h" + +// testing transparent unordered containers +#if TEST_STD_VER > 17 + +template +void test_transparent_find(Args&&... args) { + Container c{std::forward(args)...}; + Comp2Int::reset_conversions_count(); + assert(c.find(1) != c.end()); + assert(c.find(2) != c.end()); + assert(Comp2Int::get_conversions_count() == 0); + assert(c.find(3) == c.end()); + assert(Comp2Int::get_conversions_count() == 0); +} + +template +void test_non_transparent_find(Args&&... args) { + Container c{std::forward(args)...}; + Comp2Int::reset_conversions_count(); + assert(c.find(1) != c.end()); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + assert(c.find(2) != c.end()); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + assert(c.find(3) == c.end()); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); +} + +template +void test_transparent_count(Args&&... args) { + Container c(std::forward(args)...); + Comp2Int::reset_conversions_count(); + assert(c.count(1) > 0); + assert(c.count(2) > 0); + assert(Comp2Int::get_conversions_count() == 0); + assert(c.count(3) == 0); + assert(Comp2Int::get_conversions_count() == 0); +} + +template +void test_non_transparent_count(Args&&... args) { + Container c{std::forward(args)...}; + Comp2Int::reset_conversions_count(); + assert(c.count(1) > 0); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + assert(c.count(2) > 0); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + assert(c.count(3) == 0); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); +} + +template +void test_transparent_contains(Args&&... args) { + Container c{std::forward(args)...}; + Comp2Int::reset_conversions_count(); + assert(c.contains(1)); + assert(c.contains(2)); + assert(Comp2Int::get_conversions_count() == 0); + assert(!c.contains(3)); + assert(Comp2Int::get_conversions_count() == 0); +} + +template +void test_non_transparent_contains(Args&&... args) { + Container c{std::forward(args)...}; + Comp2Int::reset_conversions_count(); + assert(c.contains(1)); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + assert(c.contains(2)); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + assert(!c.contains(3)); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); +} + +template +void test_transparent_equal_range(Args&&... args) { + Container c{std::forward(args)...}; + Comp2Int::reset_conversions_count(); + auto iters = c.equal_range(1); + assert(std::distance(iters.first, iters.second) > 0); + iters = c.equal_range(2); + assert(std::distance(iters.first, iters.second) > 0); + assert(Comp2Int::get_conversions_count() == 0); + iters = c.equal_range(3); + assert(std::distance(iters.first, iters.second) == 0); + assert(Comp2Int::get_conversions_count() == 0); +} + +template +void test_non_transparent_equal_range(Args&&... args) { + Container c{std::forward(args)...}; + Comp2Int::reset_conversions_count(); + auto iters = c.equal_range(1); + assert(std::distance(iters.first, iters.second) > 0); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + iters = c.equal_range(2); + assert(std::distance(iters.first, iters.second) > 0); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); + iters = c.equal_range(3); + assert(std::distance(iters.first, iters.second) == 0); + assert(Comp2Int::get_conversions_count() > 0); + Comp2Int::reset_conversions_count(); +} + +#endif // TEST_STD_VER > 17 + +#endif // TEST_TRANSPARENT_UNORDERED_H Index: libcxx/www/cxx2a_status.html =================================================================== --- libcxx/www/cxx2a_status.html +++ libcxx/www/cxx2a_status.html @@ -120,7 +120,7 @@ P0771R1LWGstd::function move constructor should be noexceptSan DiegoComplete6.0 P0896R4LWGThe One Ranges ProposalSan Diego P0899R1LWGP0899R1 - LWG 3016 is not a defectSan DiegoNothing to do - P0919R3LWGHeterogeneous lookup for unordered containersSan Diego + P0919R3LWGHeterogeneous lookup for unordered containersSan DiegoComplete P0972R0LWG<chrono> zero(), min(), and max() should be noexceptSan DiegoComplete8.0 P1006R1LWGConstexpr in std::pointer_traitsSan DiegoComplete8.0 P1007R3LWGstd::assume_alignedSan Diego