Index: include/unordered_set =================================================================== --- include/unordered_set +++ include/unordered_set @@ -383,9 +383,9 @@ // types typedef _Value key_type; typedef key_type value_type; - typedef _Hash hasher; - typedef _Pred key_equal; - typedef _Alloc allocator_type; + typedef typename __identity<_Hash>::type hasher; + typedef typename __identity<_Pred>::type key_equal; + typedef typename __identity<_Alloc>::type allocator_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), @@ -730,6 +730,60 @@ }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template::value_type>, + class _Pred = equal_to::value_type>, + class _Allocator = allocator::value_type>, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set::value_type, _Hash, _Pred, _Allocator>; + +template, + class _Pred = equal_to<_Tp>, class _Allocator = allocator<_Tp>, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; + +template::value, void>::type> +unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_set::value_type, + hash::value_type>, + equal_to::value_type>, + _Allocator>; + +template::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, + _Hash, _Allocator) + -> unordered_set::value_type, _Hash, + equal_to::value_type>, + _Allocator>; + +template::value, void>::type> +unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + +template::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; +#endif + template unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql) @@ -983,9 +1037,9 @@ // types typedef _Value key_type; typedef key_type value_type; - typedef _Hash hasher; - typedef _Pred key_equal; - typedef _Alloc allocator_type; + typedef typename __identity<_Hash>::type hasher; + typedef typename __identity<_Pred>::type key_equal; + typedef typename __identity<_Alloc>::type allocator_type; typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same::value), @@ -1298,6 +1352,60 @@ }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template::value_type>, + class _Pred = equal_to::value_type>, + class _Allocator = allocator::value_type>, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_multiset::value_type, _Hash, _Pred, _Allocator>; + +template, + class _Pred = equal_to<_Tp>, class _Allocator = allocator<_Tp>, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; + +template::value, void>::type> +unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multiset::value_type, + hash::value_type>, + equal_to::value_type>, + _Allocator>; + +template::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, + _Hash, _Allocator) + -> unordered_multiset::value_type, _Hash, + equal_to::value_type>, + _Allocator>; + +template::value, void>::type> +unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + +template::value, void>::type, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; +#endif + template unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( size_type __n, const hasher& __hf, const key_equal& __eql) Index: test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.fail.cpp =================================================================== --- /dev/null +++ test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.fail.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset, +// Hash, Pred, Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator> +// unordered_multiset(initializer_list, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset; +// +// template +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_multiset, +// hash>, +// equal_to>, +// Allocator>; +// +// template +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_multiset, Hash, +// equal_to>, +// Allocator>; +// +// template +// unordered_multiset(initializer_list, typename see below::size_type, Allocator) +// -> unordered_multiset, equal_to, Allocator>; +// +// template +// unordered_multiset(initializer_list, typename see below::size_type, Hash, Allocator) +// -> unordered_multiset, Allocator>; + +#include +#include + +struct A {}; + +int main(int, char**) +{ + { + std::unordered_multiset s(42); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + std::unordered_multiset s(42, std::hash()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + std::unordered_multiset s(42, std::hash(), std::equal_to<>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + std::unordered_multiset s(42, std::hash(), std::equal_to<>(), std::allocator()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + std::unordered_multiset s(std::allocator{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + std::unordered_multiset s(42, std::allocator()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + std::unordered_multiset s(42, std::hash(), std::allocator()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + + return 0; +} Index: test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset, +// Hash, Pred, Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator> +// unordered_multiset(initializer_list, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset; +// +// template +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_multiset, +// hash>, +// equal_to>, +// Allocator>; +// +// template +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_multiset, Hash, +// equal_to>, +// Allocator>; +// +// template +// unordered_multiset(initializer_list, typename see below::size_type, Allocator) +// -> unordered_multiset, equal_to, Allocator>; +// +// template +// unordered_multiset(initializer_list, typename see below::size_type, Hash, Allocator) +// -> unordered_multiset, Allocator>; + +#include // is_permutation +#include +#include // INT_MAX +#include +#include + +#include "test_allocator.h" + +struct A { + friend bool operator<(A, A) { return false; } +}; + +int main(int, char**) +{ + int expected_s[] = {1, 1, 2, 3, INT_MAX}; + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_multiset s(std::begin(arr), std::end(arr)); + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_multiset s(std::begin(arr), std::end(arr), 42); + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_multiset s(std::begin(arr), std::end(arr), 42, std::hash()); + + static_assert(std::is_same_v>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_multiset s(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 40)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 40); + } + + { + std::unordered_multiset, std::equal_to<>, test_allocator> source; + std::unordered_multiset s(source); // set(set &) + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + } + + { + std::unordered_multiset, std::equal_to<>, test_allocator> source; + std::unordered_multiset s{source}; // set(set &) + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + } + + { + std::unordered_multiset, std::equal_to<>, test_allocator> source; + std::unordered_multiset s(source, test_allocator(0, 41)); + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 41); + } + + { + std::unordered_multiset, std::equal_to<>, test_allocator> source; + std::unordered_multiset s{source, test_allocator(0, 42)}; // set(set &) + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 42); + } + + { + std::unordered_multiset s{ 1, 2, 1, INT_MAX, 3 }; + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_multiset s({ 1, 2, 1, INT_MAX, 3 }, 42); + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_multiset s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash()); + + static_assert(std::is_same_v>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_multiset s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash(), std::equal_to<>()); + + static_assert(std::is_same_v, std::equal_to<>>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_multiset s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash(), std::equal_to<>(), test_allocator(0, 43)); + + static_assert(std::is_same_v, std::equal_to<>, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 43); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_multiset s(std::begin(arr), std::end(arr), 42, test_allocator(0, 44)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 44); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_multiset s(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 44)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 44); + } + + { + std::unordered_multiset s({ 1, 2, 1, INT_MAX, 3 }, 42, test_allocator(0, 43)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 43); + } + + { + std::unordered_multiset s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash(), test_allocator(0, 42)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 42); + } + + + return 0; +} Index: test/std/containers/unord/unord.set/unord.set.cnstr/deduct.fail.cpp =================================================================== --- /dev/null +++ test/std/containers/unord/unord.set/unord.set.cnstr/deduct.fail.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_set(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set, +// Hash, Pred, Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator> +// unordered_set(initializer_list, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set; +// +// template +// unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_set, +// hash>, +// equal_to>, +// Allocator>; +// +// template +// unordered_set(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_set, Hash, +// equal_to>, +// Allocator>; +// +// template +// unordered_set(initializer_list, typename see below::size_type, Allocator) +// -> unordered_set, equal_to, Allocator>; +// +// template +// unordered_set(initializer_list, typename see below::size_type, Hash, Allocator) +// -> unordered_set, Allocator>; + +#include +#include + +struct A {}; + +int main(int, char**) +{ + { + std::unordered_set s(42); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + std::unordered_set s(42, std::hash()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + std::unordered_set s(42, std::hash(), std::equal_to<>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + std::unordered_set s(42, std::hash(), std::equal_to<>(), std::allocator()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + std::unordered_set s(std::allocator{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + std::unordered_set s(42, std::allocator()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + std::unordered_set s(42, std::hash(), std::allocator()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + + return 0; +} Index: test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp @@ -0,0 +1,201 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_set(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set, +// Hash, Pred, Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator> +// unordered_set(initializer_list, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set; +// +// template +// unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_set, +// hash>, +// equal_to>, +// Allocator>; +// +// template +// unordered_set(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_set, Hash, +// equal_to>, +// Allocator>; +// +// template +// unordered_set(initializer_list, typename see below::size_type, Allocator) +// -> unordered_set, equal_to, Allocator>; +// +// template +// unordered_set(initializer_list, typename see below::size_type, Hash, Allocator) +// -> unordered_set, Allocator>; + +#include // is_permutation +#include +#include // INT_MAX +#include +#include + +#include "test_allocator.h" + +struct A { + friend bool operator<(A, A) { return false; } +}; + +int main(int, char**) +{ + int expected_s[] = {1, 2, 3, INT_MAX}; + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_set s(std::begin(arr), std::end(arr)); + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_set s(std::begin(arr), std::end(arr), 42); + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_set s(std::begin(arr), std::end(arr), 42, std::hash()); + + static_assert(std::is_same_v>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_set s(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 40)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 40); + } + + { + std::unordered_set, std::equal_to<>, test_allocator> source; + std::unordered_set s(source); // set(set &) + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + } + + { + std::unordered_set, std::equal_to<>, test_allocator> source; + std::unordered_set s{source}; // set(set &) + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + } + + { + std::unordered_set, std::equal_to<>, test_allocator> source; + std::unordered_set s(source, test_allocator(0, 41)); + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 41); + } + + { + std::unordered_set, std::equal_to<>, test_allocator> source; + std::unordered_set s{source, test_allocator(0, 42)}; // set(set &) + static_assert(std::is_same_v, ""); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 42); + } + + { + std::unordered_set s{ 1, 2, 1, INT_MAX, 3 }; + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_set s({ 1, 2, 1, INT_MAX, 3 }, 42); + + static_assert(std::is_same_v>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_set s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash()); + + static_assert(std::is_same_v>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_set s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash(), std::equal_to<>()); + + static_assert(std::is_same_v, std::equal_to<>>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + } + + { + std::unordered_set s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash(), std::equal_to<>(), test_allocator(0, 43)); + + static_assert(std::is_same_v, std::equal_to<>, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 43); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_set s(std::begin(arr), std::end(arr), 42, test_allocator(0, 44)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 44); + } + + { + const int arr[] = { 1, 2, 1, INT_MAX, 3 }; + std::unordered_set s(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 44)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 44); + } + + { + std::unordered_set s({ 1, 2, 1, INT_MAX, 3 }, 42, test_allocator(0, 43)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 43); + } + + { + std::unordered_set s({ 1, 2, 1, INT_MAX, 3 }, 42, std::hash(), test_allocator(0, 42)); + + static_assert(std::is_same_v, std::equal_to, test_allocator>>, ""); + assert(std::is_permutation(s.begin(), s.end(), std::begin(expected_s), std::end(expected_s))); + assert(s.get_allocator().get_id() == 42); + } + + + return 0; +}