diff options
author | Louis Dionne <ldionne@apple.com> | 2019-07-11 15:16:39 +0000 |
---|---|---|
committer | Louis Dionne <ldionne@apple.com> | 2019-07-11 15:16:39 +0000 |
commit | 296a80102a9b72c3eda80558fb78a3ed8849b341 (patch) | |
tree | b788343326e64bbd3b314280b92d032d5a26b155 | |
parent | 0e4386e9e773468b5589a892f812fbc6fbe2b28c (diff) | |
download | bcm5719-llvm-296a80102a9b72c3eda80558fb78a3ed8849b341.tar.gz bcm5719-llvm-296a80102a9b72c3eda80558fb78a3ed8849b341.zip |
[libc++] Implement deduction guides for <unordered_set>
Thanks to Arthur O'Dwyer for the patch.
Differential Revision: https://reviews.llvm.org/D58617
llvm-svn: 365788
5 files changed, 702 insertions, 6 deletions
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set index 3661e36a371..4a9f0309327 100644 --- a/libcxx/include/unordered_set +++ b/libcxx/include/unordered_set @@ -383,9 +383,9 @@ public: // 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_type, typename allocator_type::value_type>::value), @@ -733,6 +733,62 @@ public: }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template<class _InputIterator, + class _Hash = hash<__iter_value_type<_InputIterator>>, + class _Pred = equal_to<__iter_value_type<_InputIterator>>, + class _Allocator = allocator<__iter_value_type<_InputIterator>>, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<!__is_allocator<_Pred>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<__iter_value_type<_InputIterator>, _Hash, _Pred, _Allocator>; + +template<class _Tp, class _Hash = hash<_Tp>, + class _Pred = equal_to<_Tp>, + class _Allocator = allocator<_Tp>, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<!__is_allocator<_Pred>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +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<class _InputIterator, class _Allocator, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_set(_InputIterator, _InputIterator, + typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_set<__iter_value_type<_InputIterator>, + hash<__iter_value_type<_InputIterator>>, + equal_to<__iter_value_type<_InputIterator>>, + _Allocator>; + +template<class _InputIterator, class _Hash, class _Allocator, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_set(_InputIterator, _InputIterator, + typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_set<__iter_value_type<_InputIterator>, _Hash, + equal_to<__iter_value_type<_InputIterator>>, + _Allocator>; + +template<class _Tp, class _Allocator, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + +template<class _Tp, class _Hash, class _Allocator, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; +#endif + template <class _Value, class _Hash, class _Pred, class _Alloc> unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql) @@ -986,9 +1042,9 @@ public: // 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_type, typename allocator_type::value_type>::value), @@ -1304,6 +1360,60 @@ public: }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template<class _InputIterator, + class _Hash = hash<__iter_value_type<_InputIterator>>, + class _Pred = equal_to<__iter_value_type<_InputIterator>>, + class _Allocator = allocator<__iter_value_type<_InputIterator>>, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<!__is_allocator<_Pred>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_multiset<__iter_value_type<_InputIterator>, _Hash, _Pred, _Allocator>; + +template<class _Tp, class _Hash = hash<_Tp>, + class _Pred = equal_to<_Tp>, class _Allocator = allocator<_Tp>, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<!__is_allocator<_Pred>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +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<class _InputIterator, class _Allocator, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multiset<__iter_value_type<_InputIterator>, + hash<__iter_value_type<_InputIterator>>, + equal_to<__iter_value_type<_InputIterator>>, + _Allocator>; + +template<class _InputIterator, class _Hash, class _Allocator, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, + _Hash, _Allocator) + -> unordered_multiset<__iter_value_type<_InputIterator>, _Hash, + equal_to<__iter_value_type<_InputIterator>>, + _Allocator>; + +template<class _Tp, class _Allocator, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + +template<class _Tp, class _Hash, class _Allocator, + class = _EnableIf<!__is_allocator<_Hash>::value>, + class = _EnableIf<!is_integral<_Hash>::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; +#endif + template <class _Value, class _Hash, class _Pred, class _Alloc> unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( size_type __n, const hasher& __hf, const key_equal& __eql) diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.fail.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.fail.cpp new file mode 100644 index 00000000000..54c2a4b2bc8 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.fail.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <unordered_set> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Hash = hash<iter-value-type<InputIterator>>, +// class Pred = equal_to<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset<iter-value-type<InputIterator>, +// Hash, Pred, Allocator>; +// +// template<class T, class Hash = hash<T>, +// class Pred = equal_to<T>, class Allocator = allocator<T>> +// unordered_multiset(initializer_list<T>, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset<T, Hash, Pred, Allocator>; +// +// template<class InputIterator, class Allocator> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_multiset<iter-value-type<InputIterator>, +// hash<iter-value-type<InputIterator>>, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class InputIterator, class Hash, class Allocator> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_multiset<iter-value-type<InputIterator>, Hash, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class T, class Allocator> +// unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator) +// -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>; +// +// template<class T, class Hash, class Allocator> +// unordered_multiset(initializer_list<T>, typename see below::size_type, Hash, Allocator) +// -> unordered_multiset<T, Hash, equal_to<T>, Allocator>; + +#include <functional> +#include <unordered_set> + +int main(int, char**) +{ + { + // cannot deduce Key from nothing + std::unordered_multiset s; + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + // cannot deduce Key from just (Size) + std::unordered_multiset s(42); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + // cannot deduce Key from just (Size, Hash) + std::unordered_multiset s(42, std::hash<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred) + std::unordered_multiset s(42, std::hash<int>(), std::equal_to<>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred, Allocator) + std::unordered_multiset s(42, std::hash<int>(), std::equal_to<>(), std::allocator<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + // cannot deduce Key from just (Allocator) + std::unordered_multiset s(std::allocator<int>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + // cannot deduce Key from just (Size, Allocator) + std::unordered_multiset s(42, std::allocator<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + { + // cannot deduce Key from just (Size, Hash, Allocator) + std::unordered_multiset s(42, std::hash<short>(), std::allocator<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multiset'}} + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp new file mode 100644 index 00000000000..7becaf96009 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp @@ -0,0 +1,196 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <unordered_set> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Hash = hash<iter-value-type<InputIterator>>, +// class Pred = equal_to<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset<iter-value-type<InputIterator>, +// Hash, Pred, Allocator>; +// +// template<class T, class Hash = hash<T>, +// class Pred = equal_to<T>, class Allocator = allocator<T>> +// unordered_multiset(initializer_list<T>, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multiset<T, Hash, Pred, Allocator>; +// +// template<class InputIterator, class Allocator> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_multiset<iter-value-type<InputIterator>, +// hash<iter-value-type<InputIterator>>, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class InputIterator, class Hash, class Allocator> +// unordered_multiset(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_multiset<iter-value-type<InputIterator>, Hash, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class T, class Allocator> +// unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator) +// -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>; +// +// template<class T, class Hash, class Allocator> +// unordered_multiset(initializer_list<T>, typename see below::size_type, Hash, Allocator) +// -> unordered_multiset<T, Hash, equal_to<T>, Allocator>; + +#include <algorithm> // is_permutation +#include <cassert> +#include <climits> // INT_MAX +#include <type_traits> +#include <unordered_set> + +#include "test_allocator.h" + +int main(int, char**) +{ + const 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)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int>); + 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); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int>); + 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<short>()); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<short>>); + 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<short>(), test_allocator<int>(0, 40)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<short>, std::equal_to<int>, test_allocator<int>>); + 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<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_multiset s(source); + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + } + + { + std::unordered_multiset<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_multiset s{source}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + } + + { + std::unordered_multiset<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_multiset s(source, test_allocator<int>(0, 41)); + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 41); + } + + { + std::unordered_multiset<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_multiset s{source, test_allocator<int>(0, 42)}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 42); + } + + { + std::unordered_multiset s{ 1, 2, 1, INT_MAX, 3 }; + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int>); + 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); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int>); + 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<short>()); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<short>>); + 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<short>(), std::equal_to<>()); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<short>, 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<short>(), std::equal_to<>(), test_allocator<int>(0, 43)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<short>, std::equal_to<>, test_allocator<int>>); + 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<int>(0, 44)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, test_allocator<int>>); + 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<short>(), test_allocator<int>(0, 44)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<short>, std::equal_to<int>, test_allocator<int>>); + 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<int>(0, 43)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, test_allocator<int>>); + 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<short>(), test_allocator<int>(0, 42)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_multiset<int, std::hash<short>, std::equal_to<int>, test_allocator<int>>); + 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; +} diff --git a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.fail.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.fail.cpp new file mode 100644 index 00000000000..d4e533707c1 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.fail.cpp @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <unordered_set> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Hash = hash<iter-value-type<InputIterator>>, +// class Pred = equal_to<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// unordered_set(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set<iter-value-type<InputIterator>, +// Hash, Pred, Allocator>; +// +// template<class T, class Hash = hash<T>, +// class Pred = equal_to<T>, class Allocator = allocator<T>> +// unordered_set(initializer_list<T>, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set<T, Hash, Pred, Allocator>; +// +// template<class InputIterator, class Allocator> +// unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_set<iter-value-type<InputIterator>, +// hash<iter-value-type<InputIterator>>, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class InputIterator, class Hash, class Allocator> +// unordered_set(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_set<iter-value-type<InputIterator>, Hash, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class T, class Allocator> +// unordered_set(initializer_list<T>, typename see below::size_type, Allocator) +// -> unordered_set<T, hash<T>, equal_to<T>, Allocator>; +// +// template<class T, class Hash, class Allocator> +// unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator) +// -> unordered_set<T, Hash, equal_to<T>, Allocator>; + +#include <functional> +#include <unordered_set> + +int main(int, char**) +{ + { + // cannot deduce Key from nothing + std::unordered_set s; + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + // cannot deduce Key from just (Size) + std::unordered_set s(42); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + // cannot deduce Key from just (Size, Hash) + std::unordered_set s(42, std::hash<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred) + std::unordered_set s(42, std::hash<int>(), std::equal_to<>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred, Allocator) + std::unordered_set s(42, std::hash<int>(), std::equal_to<>(), std::allocator<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + // cannot deduce Key from just (Allocator) + std::unordered_set s(std::allocator<int>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + // cannot deduce Key from just (Size, Allocator) + std::unordered_set s(42, std::allocator<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + { + // cannot deduce Key from just (Size, Hash, Allocator) + std::unordered_set s(42, std::hash<short>(), std::allocator<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_set'}} + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp new file mode 100644 index 00000000000..20799823692 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp @@ -0,0 +1,196 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <unordered_set> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Hash = hash<iter-value-type<InputIterator>>, +// class Pred = equal_to<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// unordered_set(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set<iter-value-type<InputIterator>, +// Hash, Pred, Allocator>; +// +// template<class T, class Hash = hash<T>, +// class Pred = equal_to<T>, class Allocator = allocator<T>> +// unordered_set(initializer_list<T>, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_set<T, Hash, Pred, Allocator>; +// +// template<class InputIterator, class Allocator> +// unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_set<iter-value-type<InputIterator>, +// hash<iter-value-type<InputIterator>>, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class InputIterator, class Hash, class Allocator> +// unordered_set(InputIterator, InputIterator, typename see below::size_type, +// Hash, Allocator) +// -> unordered_set<iter-value-type<InputIterator>, Hash, +// equal_to<iter-value-type<InputIterator>>, +// Allocator>; +// +// template<class T, class Allocator> +// unordered_set(initializer_list<T>, typename see below::size_type, Allocator) +// -> unordered_set<T, hash<T>, equal_to<T>, Allocator>; +// +// template<class T, class Hash, class Allocator> +// unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator) +// -> unordered_set<T, Hash, equal_to<T>, Allocator>; + +#include <algorithm> // is_permutation +#include <cassert> +#include <climits> // INT_MAX +#include <type_traits> +#include <unordered_set> + +#include "test_allocator.h" + +int main(int, char**) +{ + const 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)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int>); + 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); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int>); + 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<short>()); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<short>>); + 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<short>(), test_allocator<int>(0, 40)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<short>, std::equal_to<int>, test_allocator<int>>); + 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<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_set s(source); + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + } + + { + std::unordered_set<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_set s{source}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + } + + { + std::unordered_set<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_set s(source, test_allocator<int>(0, 41)); + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 41); + } + + { + std::unordered_set<int, std::hash<short>, std::equal_to<>, test_allocator<int>> source; + std::unordered_set s{source, test_allocator<int>(0, 42)}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(s), decltype(source)); + assert(s.size() == 0); + assert(s.get_allocator().get_id() == 42); + } + + { + std::unordered_set s{ 1, 2, 1, INT_MAX, 3 }; + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int>); + 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); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int>); + 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<short>()); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<short>>); + 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<short>(), std::equal_to<>()); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<short>, 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<short>(), std::equal_to<>(), test_allocator<int>(0, 43)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<short>, std::equal_to<>, test_allocator<int>>); + 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<int>(0, 44)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<int>, std::equal_to<int>, test_allocator<int>>); + 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<short>(), test_allocator<int>(0, 44)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<short>, std::equal_to<int>, test_allocator<int>>); + 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<int>(0, 43)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<int>, std::equal_to<int>, test_allocator<int>>); + 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<short>(), test_allocator<int>(0, 42)); + + ASSERT_SAME_TYPE(decltype(s), std::unordered_set<int, std::hash<short>, std::equal_to<int>, test_allocator<int>>); + 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; +} |