149e08aacStbbdev /*
2*3fbdbb8bSkboyarinov Copyright (c) 2005-2022 Intel Corporation
349e08aacStbbdev
449e08aacStbbdev Licensed under the Apache License, Version 2.0 (the "License");
549e08aacStbbdev you may not use this file except in compliance with the License.
649e08aacStbbdev You may obtain a copy of the License at
749e08aacStbbdev
849e08aacStbbdev http://www.apache.org/licenses/LICENSE-2.0
949e08aacStbbdev
1049e08aacStbbdev Unless required by applicable law or agreed to in writing, software
1149e08aacStbbdev distributed under the License is distributed on an "AS IS" BASIS,
1249e08aacStbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349e08aacStbbdev See the License for the specific language governing permissions and
1449e08aacStbbdev limitations under the License.
1549e08aacStbbdev */
1649e08aacStbbdev
1749e08aacStbbdev #ifndef __TBB_concurrent_unordered_set_H
1849e08aacStbbdev #define __TBB_concurrent_unordered_set_H
1949e08aacStbbdev
2049e08aacStbbdev #include "detail/_namespace_injection.h"
2149e08aacStbbdev #include "detail/_concurrent_unordered_base.h"
2249e08aacStbbdev #include "tbb_allocator.h"
2349e08aacStbbdev
2449e08aacStbbdev namespace tbb {
2549e08aacStbbdev namespace detail {
2649e08aacStbbdev namespace d1 {
2749e08aacStbbdev
2849e08aacStbbdev template <typename Key, typename Hash, typename KeyEqual, typename Allocator, bool AllowMultimapping>
2949e08aacStbbdev struct concurrent_unordered_set_traits {
3049e08aacStbbdev using key_type = Key;
3149e08aacStbbdev using value_type = key_type;
3249e08aacStbbdev using allocator_type = Allocator;
3349e08aacStbbdev using hash_compare_type = hash_compare<key_type, Hash, KeyEqual>;
3449e08aacStbbdev static constexpr bool allow_multimapping = AllowMultimapping;
3549e08aacStbbdev
get_keyconcurrent_unordered_set_traits3649e08aacStbbdev static constexpr const key_type& get_key( const value_type& value ) {
3749e08aacStbbdev return value;
3849e08aacStbbdev }
3949e08aacStbbdev }; // class concurrent_unordered_set_traits
4049e08aacStbbdev
4149e08aacStbbdev template <typename Key, typename Hash, typename KeyEqual, typename Allocator>
4249e08aacStbbdev class concurrent_unordered_multiset;
4349e08aacStbbdev
4449e08aacStbbdev template <typename Key, typename Hash = std::hash<Key>, typename KeyEqual = std::equal_to<Key>,
4549e08aacStbbdev typename Allocator = tbb::tbb_allocator<Key>>
4649e08aacStbbdev class concurrent_unordered_set
4749e08aacStbbdev : public concurrent_unordered_base<concurrent_unordered_set_traits<Key, Hash, KeyEqual, Allocator, false>>
4849e08aacStbbdev {
4949e08aacStbbdev using traits_type = concurrent_unordered_set_traits<Key, Hash, KeyEqual, Allocator, false>;
5049e08aacStbbdev using base_type = concurrent_unordered_base<traits_type>;
5149e08aacStbbdev public:
5249e08aacStbbdev using key_type = typename base_type::key_type;
5349e08aacStbbdev using value_type = typename base_type::value_type;
5449e08aacStbbdev using size_type = typename base_type::size_type;
5549e08aacStbbdev using difference_type = typename base_type::difference_type;
5649e08aacStbbdev using hasher = typename base_type::hasher;
5749e08aacStbbdev using key_equal = typename base_type::key_equal;
5849e08aacStbbdev using allocator_type = typename base_type::allocator_type;
5949e08aacStbbdev using reference = typename base_type::reference;
6049e08aacStbbdev using const_reference = typename base_type::const_reference;
6149e08aacStbbdev using pointer = typename base_type::pointer;
6249e08aacStbbdev using const_pointer = typename base_type::const_pointer;
6349e08aacStbbdev using iterator = typename base_type::iterator;
6449e08aacStbbdev using const_iterator = typename base_type::const_iterator;
6549e08aacStbbdev using local_iterator = typename base_type::local_iterator;
6649e08aacStbbdev using const_local_iterator = typename base_type::const_local_iterator;
6749e08aacStbbdev using node_type = typename base_type::node_type;
6849e08aacStbbdev
6949e08aacStbbdev // Include constructors of base_type;
7049e08aacStbbdev using base_type::base_type;
712713d41eSIlya Isaev
72d86ed7fbStbbdev // Required for implicit deduction guides
73d86ed7fbStbbdev concurrent_unordered_set() = default;
74d86ed7fbStbbdev concurrent_unordered_set( const concurrent_unordered_set& ) = default;
concurrent_unordered_set(const concurrent_unordered_set & other,const allocator_type & alloc)75d86ed7fbStbbdev concurrent_unordered_set( const concurrent_unordered_set& other, const allocator_type& alloc ) : base_type(other, alloc) {}
76d86ed7fbStbbdev concurrent_unordered_set( concurrent_unordered_set&& ) = default;
concurrent_unordered_set(concurrent_unordered_set && other,const allocator_type & alloc)77d86ed7fbStbbdev concurrent_unordered_set( concurrent_unordered_set&& other, const allocator_type& alloc ) : base_type(std::move(other), alloc) {}
78d86ed7fbStbbdev // Required to respect the rule of 5
79d86ed7fbStbbdev concurrent_unordered_set& operator=( const concurrent_unordered_set& ) = default;
80d86ed7fbStbbdev concurrent_unordered_set& operator=( concurrent_unordered_set&& ) = default;
8149e08aacStbbdev
822713d41eSIlya Isaev concurrent_unordered_set& operator=( std::initializer_list<value_type> il ) {
832713d41eSIlya Isaev base_type::operator= (il);
842713d41eSIlya Isaev return *this;
852713d41eSIlya Isaev }
862713d41eSIlya Isaev
8749e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_set<key_type,OtherHash,OtherKeyEqual,allocator_type> & source)8849e08aacStbbdev void merge( concurrent_unordered_set<key_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
8949e08aacStbbdev this->internal_merge(source);
9049e08aacStbbdev }
9149e08aacStbbdev
9249e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_set<key_type,OtherHash,OtherKeyEqual,allocator_type> && source)9349e08aacStbbdev void merge( concurrent_unordered_set<key_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
9449e08aacStbbdev this->internal_merge(std::move(source));
9549e08aacStbbdev }
9649e08aacStbbdev
9749e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_multiset<key_type,OtherHash,OtherKeyEqual,allocator_type> & source)9849e08aacStbbdev void merge( concurrent_unordered_multiset<key_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
9949e08aacStbbdev this->internal_merge(source);
10049e08aacStbbdev }
10149e08aacStbbdev
10249e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_multiset<key_type,OtherHash,OtherKeyEqual,allocator_type> && source)10349e08aacStbbdev void merge( concurrent_unordered_multiset<key_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
10449e08aacStbbdev this->internal_merge(std::move(source));
10549e08aacStbbdev }
10649e08aacStbbdev }; // class concurrent_unordered_set
10749e08aacStbbdev
10849e08aacStbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
10949e08aacStbbdev
110d86ed7fbStbbdev template <typename It,
111d86ed7fbStbbdev typename Hash = std::hash<iterator_value_t<It>>,
112d86ed7fbStbbdev typename KeyEq = std::equal_to<iterator_value_t<It>>,
113d86ed7fbStbbdev typename Alloc = tbb::tbb_allocator<iterator_value_t<It>>,
114d86ed7fbStbbdev typename = std::enable_if_t<is_input_iterator_v<It>>,
115d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
116d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
117d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
118d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
119d86ed7fbStbbdev concurrent_unordered_set( It, It, std::size_t = {}, Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
120d86ed7fbStbbdev -> concurrent_unordered_set<iterator_value_t<It>, Hash, KeyEq, Alloc>;
12149e08aacStbbdev
122d86ed7fbStbbdev template <typename T,
123d86ed7fbStbbdev typename Hash = std::hash<T>,
124d86ed7fbStbbdev typename KeyEq = std::equal_to<T>,
125d86ed7fbStbbdev typename Alloc = tbb::tbb_allocator<T>,
126d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
127d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
128d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
129d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
130d86ed7fbStbbdev concurrent_unordered_set( std::initializer_list<T>, std::size_t = {},
131d86ed7fbStbbdev Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
132d86ed7fbStbbdev -> concurrent_unordered_set<T, Hash, KeyEq, Alloc>;
13349e08aacStbbdev
134d86ed7fbStbbdev template <typename It, typename Alloc,
135d86ed7fbStbbdev typename = std::enable_if_t<is_input_iterator_v<It>>,
136d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>>
137d86ed7fbStbbdev concurrent_unordered_set( It, It, std::size_t, Alloc )
138d86ed7fbStbbdev -> concurrent_unordered_set<iterator_value_t<It>, std::hash<iterator_value_t<It>>,
139d86ed7fbStbbdev std::equal_to<iterator_value_t<It>>, Alloc>;
14049e08aacStbbdev
141d86ed7fbStbbdev template <typename It, typename Hash, typename Alloc,
142d86ed7fbStbbdev typename = std::enable_if_t<is_input_iterator_v<It>>,
143d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
144d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
145d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
146d86ed7fbStbbdev concurrent_unordered_set( It, It, std::size_t, Hash, Alloc )
147d86ed7fbStbbdev -> concurrent_unordered_set<iterator_value_t<It>, Hash, std::equal_to<iterator_value_t<It>>, Alloc>;
14849e08aacStbbdev
149d86ed7fbStbbdev template <typename T, typename Alloc,
150d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>>
151d86ed7fbStbbdev concurrent_unordered_set( std::initializer_list<T>, std::size_t, Alloc )
152d86ed7fbStbbdev -> concurrent_unordered_set<T, std::hash<T>, std::equal_to<T>, Alloc>;
15349e08aacStbbdev
154d86ed7fbStbbdev template <typename T, typename Alloc,
155d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>>
156d86ed7fbStbbdev concurrent_unordered_set( std::initializer_list<T>, Alloc )
157d86ed7fbStbbdev -> concurrent_unordered_set<T, std::hash<T>, std::equal_to<T>, Alloc>;
15849e08aacStbbdev
159d86ed7fbStbbdev template <typename T, typename Hash, typename Alloc,
160d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
161d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
162d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
163d86ed7fbStbbdev concurrent_unordered_set( std::initializer_list<T>, std::size_t, Hash, Alloc )
164d86ed7fbStbbdev -> concurrent_unordered_set<T, Hash, std::equal_to<T>, Alloc>;
16549e08aacStbbdev
166*3fbdbb8bSkboyarinov #if __APPLE__ && __TBB_CLANG_VERSION == 100000
167*3fbdbb8bSkboyarinov // An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
168*3fbdbb8bSkboyarinov // due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
169*3fbdbb8bSkboyarinov // Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
170*3fbdbb8bSkboyarinov // The issue reproduces only on this version of the compiler
171*3fbdbb8bSkboyarinov template <typename T, typename Hash, typename KeyEq, typename Alloc>
172*3fbdbb8bSkboyarinov concurrent_unordered_set( concurrent_unordered_set<T, Hash, KeyEq, Alloc>, Alloc )
173*3fbdbb8bSkboyarinov -> concurrent_unordered_set<T, Hash, KeyEq, Alloc>;
174*3fbdbb8bSkboyarinov #endif
17549e08aacStbbdev #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
17649e08aacStbbdev
17749e08aacStbbdev template <typename Key, typename Hash, typename KeyEqual, typename Allocator>
swap(concurrent_unordered_set<Key,Hash,KeyEqual,Allocator> & lhs,concurrent_unordered_set<Key,Hash,KeyEqual,Allocator> & rhs)17849e08aacStbbdev void swap( concurrent_unordered_set<Key, Hash, KeyEqual, Allocator>& lhs,
17949e08aacStbbdev concurrent_unordered_set<Key, Hash, KeyEqual, Allocator>& rhs ) {
18049e08aacStbbdev lhs.swap(rhs);
18149e08aacStbbdev }
18249e08aacStbbdev
18349e08aacStbbdev template <typename Key, typename Hash = std::hash<Key>, typename KeyEqual = std::equal_to<Key>,
18449e08aacStbbdev typename Allocator = tbb::tbb_allocator<Key>>
18549e08aacStbbdev class concurrent_unordered_multiset
18649e08aacStbbdev : public concurrent_unordered_base<concurrent_unordered_set_traits<Key, Hash, KeyEqual, Allocator, true>>
18749e08aacStbbdev {
18849e08aacStbbdev using traits_type = concurrent_unordered_set_traits<Key, Hash, KeyEqual, Allocator, true>;
18949e08aacStbbdev using base_type = concurrent_unordered_base<traits_type>;
19049e08aacStbbdev public:
19149e08aacStbbdev using key_type = typename base_type::key_type;
19249e08aacStbbdev using value_type = typename base_type::value_type;
19349e08aacStbbdev using size_type = typename base_type::size_type;
19449e08aacStbbdev using difference_type = typename base_type::difference_type;
19549e08aacStbbdev using hasher = typename base_type::hasher;
19649e08aacStbbdev using key_equal = typename base_type::key_equal;
19749e08aacStbbdev using allocator_type = typename base_type::allocator_type;
19849e08aacStbbdev using reference = typename base_type::reference;
19949e08aacStbbdev using const_reference = typename base_type::const_reference;
20049e08aacStbbdev using pointer = typename base_type::pointer;
20149e08aacStbbdev using const_pointer = typename base_type::const_pointer;
20249e08aacStbbdev using iterator = typename base_type::iterator;
20349e08aacStbbdev using const_iterator = typename base_type::const_iterator;
20449e08aacStbbdev using local_iterator = typename base_type::local_iterator;
20549e08aacStbbdev using const_local_iterator = typename base_type::const_local_iterator;
20649e08aacStbbdev using node_type = typename base_type::node_type;
20749e08aacStbbdev
20849e08aacStbbdev // Include constructors of base_type;
20949e08aacStbbdev using base_type::base_type;
21049e08aacStbbdev
211d86ed7fbStbbdev // Required for implicit deduction guides
212d86ed7fbStbbdev concurrent_unordered_multiset() = default;
213d86ed7fbStbbdev concurrent_unordered_multiset( const concurrent_unordered_multiset& ) = default;
concurrent_unordered_multiset(const concurrent_unordered_multiset & other,const allocator_type & alloc)214d86ed7fbStbbdev concurrent_unordered_multiset( const concurrent_unordered_multiset& other, const allocator_type& alloc ) : base_type(other, alloc) {}
215d86ed7fbStbbdev concurrent_unordered_multiset( concurrent_unordered_multiset&& ) = default;
concurrent_unordered_multiset(concurrent_unordered_multiset && other,const allocator_type & alloc)216d86ed7fbStbbdev concurrent_unordered_multiset( concurrent_unordered_multiset&& other, const allocator_type& alloc ) : base_type(std::move(other), alloc) {}
217d86ed7fbStbbdev // Required to respect the rule of 5
218d86ed7fbStbbdev concurrent_unordered_multiset& operator=( const concurrent_unordered_multiset& ) = default;
219d86ed7fbStbbdev concurrent_unordered_multiset& operator=( concurrent_unordered_multiset&& ) = default;
220d86ed7fbStbbdev
2212713d41eSIlya Isaev concurrent_unordered_multiset& operator=( std::initializer_list<value_type> il ) {
2222713d41eSIlya Isaev base_type::operator= (il);
2232713d41eSIlya Isaev return *this;
2242713d41eSIlya Isaev }
2252713d41eSIlya Isaev
22649e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_set<key_type,OtherHash,OtherKeyEqual,allocator_type> & source)22749e08aacStbbdev void merge( concurrent_unordered_set<key_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
22849e08aacStbbdev this->internal_merge(source);
22949e08aacStbbdev }
23049e08aacStbbdev
23149e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_set<key_type,OtherHash,OtherKeyEqual,allocator_type> && source)23249e08aacStbbdev void merge( concurrent_unordered_set<key_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
23349e08aacStbbdev this->internal_merge(std::move(source));
23449e08aacStbbdev }
23549e08aacStbbdev
23649e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_multiset<key_type,OtherHash,OtherKeyEqual,allocator_type> & source)23749e08aacStbbdev void merge( concurrent_unordered_multiset<key_type, OtherHash, OtherKeyEqual, allocator_type>& source ) {
23849e08aacStbbdev this->internal_merge(source);
23949e08aacStbbdev }
24049e08aacStbbdev
24149e08aacStbbdev template <typename OtherHash, typename OtherKeyEqual>
merge(concurrent_unordered_multiset<key_type,OtherHash,OtherKeyEqual,allocator_type> && source)24249e08aacStbbdev void merge( concurrent_unordered_multiset<key_type, OtherHash, OtherKeyEqual, allocator_type>&& source ) {
24349e08aacStbbdev this->internal_merge(std::move(source));
24449e08aacStbbdev }
24549e08aacStbbdev }; // class concurrent_unordered_multiset
24649e08aacStbbdev
24749e08aacStbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
248d86ed7fbStbbdev template <typename It,
249d86ed7fbStbbdev typename Hash = std::hash<iterator_value_t<It>>,
250d86ed7fbStbbdev typename KeyEq = std::equal_to<iterator_value_t<It>>,
251d86ed7fbStbbdev typename Alloc = tbb::tbb_allocator<iterator_value_t<It>>,
252d86ed7fbStbbdev typename = std::enable_if_t<is_input_iterator_v<It>>,
253d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
254d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
255d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
256d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
257d86ed7fbStbbdev concurrent_unordered_multiset( It, It, std::size_t = {}, Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
258d86ed7fbStbbdev -> concurrent_unordered_multiset<iterator_value_t<It>, Hash, KeyEq, Alloc>;
25949e08aacStbbdev
260d86ed7fbStbbdev template <typename T,
261d86ed7fbStbbdev typename Hash = std::hash<T>,
262d86ed7fbStbbdev typename KeyEq = std::equal_to<T>,
263d86ed7fbStbbdev typename Alloc = tbb::tbb_allocator<T>,
264d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
265d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
266d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<KeyEq>>,
267d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
268d86ed7fbStbbdev concurrent_unordered_multiset( std::initializer_list<T>, std::size_t = {},
269d86ed7fbStbbdev Hash = Hash(), KeyEq = KeyEq(), Alloc = Alloc() )
270d86ed7fbStbbdev -> concurrent_unordered_multiset<T, Hash, KeyEq, Alloc>;
27149e08aacStbbdev
272d86ed7fbStbbdev template <typename It, typename Alloc,
273d86ed7fbStbbdev typename = std::enable_if_t<is_input_iterator_v<It>>,
274d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>>
275d86ed7fbStbbdev concurrent_unordered_multiset( It, It, std::size_t, Alloc )
276d86ed7fbStbbdev -> concurrent_unordered_multiset<iterator_value_t<It>, std::hash<iterator_value_t<It>>,
277d86ed7fbStbbdev std::equal_to<iterator_value_t<It>>, Alloc>;
27849e08aacStbbdev
279d86ed7fbStbbdev template <typename It, typename Hash, typename Alloc,
280d86ed7fbStbbdev typename = std::enable_if_t<is_input_iterator_v<It>>,
281d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
282d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
283d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
284d86ed7fbStbbdev concurrent_unordered_multiset( It, It, std::size_t, Hash, Alloc )
285d86ed7fbStbbdev -> concurrent_unordered_multiset<iterator_value_t<It>, Hash, std::equal_to<iterator_value_t<It>>, Alloc>;
28649e08aacStbbdev
287d86ed7fbStbbdev template <typename T, typename Alloc,
288d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>>
289d86ed7fbStbbdev concurrent_unordered_multiset( std::initializer_list<T>, std::size_t, Alloc )
290d86ed7fbStbbdev -> concurrent_unordered_multiset<T, std::hash<T>, std::equal_to<T>, Alloc>;
291d86ed7fbStbbdev
292d86ed7fbStbbdev template <typename T, typename Alloc,
293d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>>
294d86ed7fbStbbdev concurrent_unordered_multiset( std::initializer_list<T>, Alloc )
295d86ed7fbStbbdev -> concurrent_unordered_multiset<T, std::hash<T>, std::equal_to<T>, Alloc>;
296d86ed7fbStbbdev
297d86ed7fbStbbdev template <typename T, typename Hash, typename Alloc,
298d86ed7fbStbbdev typename = std::enable_if_t<is_allocator_v<Alloc>>,
299d86ed7fbStbbdev typename = std::enable_if_t<!is_allocator_v<Hash>>,
300d86ed7fbStbbdev typename = std::enable_if_t<!std::is_integral_v<Hash>>>
301d86ed7fbStbbdev concurrent_unordered_multiset( std::initializer_list<T>, std::size_t, Hash, Alloc )
302d86ed7fbStbbdev -> concurrent_unordered_multiset<T, Hash, std::equal_to<T>, Alloc>;
30349e08aacStbbdev
304*3fbdbb8bSkboyarinov #if __APPLE__ && __TBB_CLANG_VERSION == 100000
305*3fbdbb8bSkboyarinov // An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
306*3fbdbb8bSkboyarinov // due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
307*3fbdbb8bSkboyarinov // Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
308*3fbdbb8bSkboyarinov // The issue reproduces only on this version of the compiler
309*3fbdbb8bSkboyarinov template <typename T, typename Hash, typename KeyEq, typename Alloc>
310*3fbdbb8bSkboyarinov concurrent_unordered_multiset( concurrent_unordered_multiset<T, Hash, KeyEq, Alloc>, Alloc )
311*3fbdbb8bSkboyarinov -> concurrent_unordered_multiset<T, Hash, KeyEq, Alloc>;
312*3fbdbb8bSkboyarinov #endif
31349e08aacStbbdev #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
31449e08aacStbbdev
31549e08aacStbbdev template <typename Key, typename Hash, typename KeyEqual, typename Allocator>
swap(concurrent_unordered_multiset<Key,Hash,KeyEqual,Allocator> & lhs,concurrent_unordered_multiset<Key,Hash,KeyEqual,Allocator> & rhs)31649e08aacStbbdev void swap( concurrent_unordered_multiset<Key, Hash, KeyEqual, Allocator>& lhs,
31749e08aacStbbdev concurrent_unordered_multiset<Key, Hash, KeyEqual, Allocator>& rhs ) {
31849e08aacStbbdev lhs.swap(rhs);
31949e08aacStbbdev }
32049e08aacStbbdev
32149e08aacStbbdev } // namespace d1
32249e08aacStbbdev } // namespace detail
32349e08aacStbbdev
32449e08aacStbbdev inline namespace v1 {
32549e08aacStbbdev
32649e08aacStbbdev using detail::d1::concurrent_unordered_set;
32749e08aacStbbdev using detail::d1::concurrent_unordered_multiset;
32849e08aacStbbdev using detail::split;
32949e08aacStbbdev
33049e08aacStbbdev } // inline namespace v1
33149e08aacStbbdev } // namespace tbb
33249e08aacStbbdev
33349e08aacStbbdev #endif // __TBB_concurrent_unordered_set_H
334