Index: include/map =================================================================== --- include/map +++ include/map @@ -191,10 +191,15 @@ iterator find(const K& x); // C++14 template const_iterator find(const K& x) const; // C++14 + template size_type count(const K& x) const; // C++14 - size_type count(const key_type& k) const; + + bool contains(const key_type& x) const; // C++20 + template + bool contains(const K& x) const; // C++20 + iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -405,10 +410,15 @@ iterator find(const K& x); // C++14 template const_iterator find(const K& x) const; // C++14 - template - size_type count(const K& x) const; // C++14 + template + size_type count(const K& x) const; // C++14 size_type count(const key_type& k) const; + + bool contains(const key_type& x) const; // C++20 + template + bool contains(const K& x) const; // C++20 + iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -1394,6 +1404,16 @@ typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type + contains(const _K2& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} @@ -2021,6 +2041,16 @@ typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type + contains(const _K2& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} Index: include/set =================================================================== --- include/set +++ include/set @@ -154,10 +154,15 @@ iterator find(const K& x); template const_iterator find(const K& x) const; // C++14 + template size_type count(const K& x) const; // C++14 - size_type count(const key_type& k) const; + + bool contains(const key_type& x) const; // C++20 + template + bool contains(const K& x) const; // C++20 + iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -355,7 +360,14 @@ template const_iterator find(const K& x) const; // C++14 + template + size_type count(const K& x) const; // C++14 size_type count(const key_type& k) const; + + bool contains(const key_type& x) const; // C++20 + template + bool contains(const K& x) const; // C++20 + iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -783,6 +795,16 @@ typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type + contains(const _K2& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} @@ -1271,6 +1293,15 @@ count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type + contains(const _K2& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} Index: include/unordered_map =================================================================== --- include/unordered_map +++ include/unordered_map @@ -79,12 +79,12 @@ unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_map(f, l, n, hasher(), key_equal(), a) {} // C++14 template - unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, + unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(f, l, n, hf, key_equal(), a) {} // C++14 unordered_map(initializer_list il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) {} // C++14 - unordered_map(initializer_list il, size_type n, const hasher& hf, + unordered_map(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(il, n, hf, key_equal(), a) {} // C++14 ~unordered_map(); @@ -174,6 +174,7 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; + bool contains(const key_type& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -277,12 +278,12 @@ unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_multimap(f, l, n, hasher(), key_equal(), a) {} // C++14 template - unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, + unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(f, l, n, hf, key_equal(), a) {} // C++14 unordered_multimap(initializer_list il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) {} // C++14 - unordered_multimap(initializer_list il, size_type n, const hasher& hf, + unordered_multimap(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(il, n, hf, key_equal(), a) {} // C++14 ~unordered_multimap(); @@ -355,6 +356,7 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; + bool contains(const key_type& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -952,14 +954,14 @@ : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY - unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, + unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__first, __last, __n, __hf, key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_map(initializer_list __il, size_type __n, const allocator_type& __a) : unordered_map(__il, __n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY - unordered_map(initializer_list __il, size_type __n, const hasher& __hf, + unordered_map(initializer_list __il, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__il, __n, __hf, key_equal(), __a) {} #endif @@ -1273,8 +1275,15 @@ 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);} + _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} @@ -1776,14 +1785,14 @@ : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) {} template _LIBCPP_INLINE_VISIBILITY - unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, + unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY unordered_multimap(initializer_list __il, size_type __n, const allocator_type& __a) : unordered_multimap(__il, __n, hasher(), key_equal(), __a) {} _LIBCPP_INLINE_VISIBILITY - unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf, + unordered_multimap(initializer_list __il, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__il, __n, __hf, key_equal(), __a) {} #endif @@ -1974,8 +1983,15 @@ 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);} + _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} Index: include/unordered_set =================================================================== --- include/unordered_set +++ include/unordered_set @@ -146,6 +146,7 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; + bool contains(const key_type& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -310,6 +311,7 @@ iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; + bool contains(const key_type& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -674,6 +676,12 @@ const_iterator find(const key_type& __k) const {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} @@ -1242,6 +1250,12 @@ const_iterator find(const key_type& __k) const {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} Index: test/std/containers/contains.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/contains.pass.cpp @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +#include +#include +#include +#include +#include + +// +// +// +// + +// bool contains(const key_type& x) const; +// template bool contains(const K& x) const; + +template +void test_map(B bad, Pairs... args) { + T map; + P pairs[] = {args...}; + + for (auto& p : pairs) map.insert(p); + for (auto& p : pairs) assert(map.contains(p.first)); + + assert(!map.contains(bad)); +} + +template +void test_set(B bad, Vals... args) { + T set; + V vals[] = {args...}; + + for (auto& v : vals) set.insert(v); + for (auto& v : vals) assert(set.contains(v)); + + assert(!set.contains(bad)); +} + +struct E { int a = 1; double b = 1; char c = 1; }; + +int main(int, char**) +{ + { + test_map, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test_map, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test_map, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + { + test_map, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test_map, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test_map, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + { + test_map, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test_map, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test_map, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + { + test_map, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test_map, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test_map, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + { + test_set, int>(14, 10, 11, 12, 13); + test_set, char>('e', 'a', 'b', 'c', 'd'); + } + { + test_set, int>(14, 10, 11, 12, 13); + test_set, char>('e', 'a', 'b', 'c', 'd'); + } + { + test_set, int>(14, 10, 11, 12, 13); + test_set, char>('e', 'a', 'b', 'c', 'd'); + } + { + test_set, int>(14, 10, 11, 12, 13); + test_set, char>('e', 'a', 'b', 'c', 'd'); + } + + return 0; +} + Index: www/cxx2a_status.html =================================================================== --- www/cxx2a_status.html +++ www/cxx2a_status.html @@ -83,7 +83,7 @@ P0019R8LWGAtomic RefRapperswil - P0458R2LWGChecking for Existence of an Element in Associative ContainersRapperswil + P0458R2LWGChecking for Existence of an Element in Associative ContainersRapperswilComplete P0475R1LWGLWG 2511: guaranteed copy elision for piecewise constructionRapperswil P0476R2LWGBit-casting object representationsRapperswil P0528R3CWGThe Curious Case of Padding Bits, Featuring Atomic Compare-and-ExchangeRapperswil