diff options
8 files changed, 775 insertions, 4 deletions
diff --git a/libcxx/include/iterator b/libcxx/include/iterator index e73b4b713ed..30801ea83db 100644 --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -538,6 +538,22 @@ struct __is_exactly_input_iterator __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value && !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template<class _InputIterator> +using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; + +template<class _InputIterator> +using __iter_key_type = remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>; + +template<class _InputIterator> +using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; + +template<class _InputIterator> +using __iter_to_alloc_type = pair< + add_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>, + typename iterator_traits<_InputIterator>::value_type::second_type>; +#endif + template<class _Category, class _Tp, class _Distance = ptrdiff_t, class _Pointer = _Tp*, class _Reference = _Tp&> struct _LIBCPP_TEMPLATE_VIS iterator diff --git a/libcxx/include/map b/libcxx/include/map index a8bf448dd57..6805a513394 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -902,8 +902,8 @@ public: typedef _Key key_type; typedef _Tp mapped_type; typedef pair<const key_type, mapped_type> value_type; - typedef _Compare key_compare; - typedef _Allocator allocator_type; + typedef typename __identity<_Compare>::type key_compare; + typedef typename __identity<_Allocator>::type allocator_type; typedef value_type& reference; typedef const value_type& const_reference; @@ -1465,6 +1465,32 @@ private: #endif }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>, + class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +map(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) + -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; + +template<class _Key, class _Tp, class _Compare = less<remove_const_t<_Key>>, + class _Allocator = allocator<pair<const _Key, _Tp>>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +map(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare(), _Allocator = _Allocator()) + -> map<remove_const_t<_Key>, _Tp, _Compare, _Allocator>; + +template<class _InputIterator, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +map(_InputIterator, _InputIterator, _Allocator) + -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + less<__iter_key_type<_InputIterator>>, _Allocator>; + +template<class _Key, class _Tp, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +map(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> map<remove_const_t<_Key>, _Tp, less<remove_const_t<_Key>>, _Allocator>; +#endif #ifndef _LIBCPP_CXX03_LANG template <class _Key, class _Tp, class _Compare, class _Allocator> @@ -1637,8 +1663,8 @@ public: typedef _Key key_type; typedef _Tp mapped_type; typedef pair<const key_type, mapped_type> value_type; - typedef _Compare key_compare; - typedef _Allocator allocator_type; + typedef typename __identity<_Compare>::type key_compare; + typedef typename __identity<_Allocator>::type allocator_type; typedef value_type& reference; typedef const value_type& const_reference; @@ -2090,6 +2116,33 @@ private: typedef unique_ptr<__node, _Dp> __node_holder; }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>, + class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multimap(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; + +template<class _Key, class _Tp, class _Compare = less<remove_const_t<_Key>>, + class _Allocator = allocator<pair<const _Key, _Tp>>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multimap(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<remove_const_t<_Key>, _Tp, _Compare, _Allocator>; + +template<class _InputIterator, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multimap(_InputIterator, _InputIterator, _Allocator) + -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + less<__iter_key_type<_InputIterator>>, _Allocator>; + +template<class _Key, class _Tp, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> multimap<remove_const_t<_Key>, _Tp, less<remove_const_t<_Key>>, _Allocator>; +#endif + #ifndef _LIBCPP_CXX03_LANG template <class _Key, class _Tp, class _Compare, class _Allocator> multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const allocator_type& __a) diff --git a/libcxx/test/std/containers/associative/map/map.cons/deduct.fail.cpp b/libcxx/test/std/containers/associative/map/map.cons/deduct.fail.cpp new file mode 100644 index 00000000000..2e719da6442 --- /dev/null +++ b/libcxx/test/std/containers/associative/map/map.cons/deduct.fail.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <map> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides +// XFAIL: clang-6, apple-clang-9.0, apple-clang-9.1, apple-clang-10.0 +// clang-6 gives different error messages. + +// template<class InputIterator, +// class Compare = less<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// map(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> map<iter-value-type<InputIterator>, Compare, Allocator>; +// template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> +// map(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) +// -> map<Key, Compare, Allocator>; +// template<class InputIterator, class Allocator> +// map(InputIterator, InputIterator, Allocator) +// -> map<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; +// template<class Key, class Allocator> +// map(initializer_list<Key>, Allocator) +// -> map<Key, less<Key>, Allocator>; + +#include <climits> // INT_MAX +#include <functional> +#include <map> +#include <type_traits> + +struct NotAnAllocator { + friend bool operator<(NotAnAllocator, NotAnAllocator) { return false; } +}; + +using P = std::pair<int, long>; +using PC = std::pair<const int, long>; + +int main(int, char**) +{ + { + // cannot deduce Key and T from nothing + std::map m; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // cannot deduce Key and T from just (Compare) + std::map m(std::less<int>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // cannot deduce Key and T from just (Compare, Allocator) + std::map m(std::less<int>{}, std::allocator<PC>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // cannot deduce Key and T from just (Allocator) + std::map m(std::allocator<PC>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // refuse to rebind the allocator if Allocator::value_type is not exactly what we expect + const P arr[] = { {1,1L}, {2,2L}, {3,3L} }; + std::map m(arr, arr + 3, std::allocator<P>()); + // expected-error-re@map:* {{static_assert failed{{( due to requirement '.*')?}} "Allocator::value_type must be same type as value_type"}} + } + { + // cannot convert from some arbitrary unrelated type + NotAnAllocator a; + std::map m(a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::map m{ {1,1L}, {2,2L}, {3,3L} }; + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::map m({ {1,1L}, {2,2L}, {3,3L} }, std::less<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::map m({ {1,1L}, {2,2L}, {3,3L} }, std::less<int>(), std::allocator<PC>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::map m({ {1,1L}, {2,2L}, {3,3L} }, std::allocator<PC>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // since we have parens, not braces, this deliberately does not find the initializer_list constructor + std::map m(P{1,1L}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + // since we have parens, not braces, this deliberately does not find the initializer_list constructor + std::map m(PC{1,1L}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + + return 0; +} diff --git a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp new file mode 100644 index 00000000000..9075d27106d --- /dev/null +++ b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <map> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Compare = less<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// map(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> map<iter-value-type<InputIterator>, Compare, Allocator>; +// template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> +// map(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) +// -> map<Key, Compare, Allocator>; +// template<class InputIterator, class Allocator> +// map(InputIterator, InputIterator, Allocator) +// -> map<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; +// template<class Key, class Allocator> +// map(initializer_list<Key>, Allocator) +// -> map<Key, less<Key>, Allocator>; + +#include <algorithm> // std::equal +#include <cassert> +#include <climits> // INT_MAX +#include <functional> +#include <map> +#include <type_traits> + +#include "test_allocator.h" + +using P = std::pair<int, long>; +using PC = std::pair<const int, long>; + +int main(int, char**) +{ + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::map m(std::begin(arr), std::end(arr)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long>); + const PC expected_m[] = { {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::map m(std::begin(arr), std::end(arr), std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::greater<int>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::map m(std::begin(arr), std::end(arr), std::greater<int>(), test_allocator<PC>(0, 42)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::greater<int>, test_allocator<PC>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 42); + } + + { + std::map<int, long> source; + std::map m(source); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::map<int, long> source; + std::map m{source}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::map<int, long> source; + std::map m(source, std::map<int, long>::allocator_type()); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::map m{ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }; + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long>); + const PC expected_m[] = { {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::greater<int>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, std::greater<int>(), test_allocator<PC>(0, 43)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::greater<int>, test_allocator<PC>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 43); + } + + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::map m(std::begin(arr), std::end(arr), test_allocator<PC>(0, 44)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::less<int>, test_allocator<PC>>); + const PC expected_m[] = { {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + std::map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, test_allocator<PC>(0, 45)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::less<int>, test_allocator<PC>>); + const PC expected_m[] = { {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + return 0; +} diff --git a/libcxx/test/std/containers/associative/map/map.cons/deduct_const.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/deduct_const.pass.cpp new file mode 100644 index 00000000000..77785363403 --- /dev/null +++ b/libcxx/test/std/containers/associative/map/map.cons/deduct_const.pass.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <map> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Compare = less<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// map(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> map<iter-value-type<InputIterator>, Compare, Allocator>; +// template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> +// map(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) +// -> map<Key, Compare, Allocator>; +// template<class InputIterator, class Allocator> +// map(InputIterator, InputIterator, Allocator) +// -> map<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; +// template<class Key, class Allocator> +// map(initializer_list<Key>, Allocator) +// -> map<Key, less<Key>, Allocator>; + +#include <algorithm> // std::equal +#include <cassert> +#include <climits> // INT_MAX +#include <functional> +#include <map> +#include <type_traits> + +#include "test_allocator.h" + +using P = std::pair<int, long>; +using PC = std::pair<const int, long>; +using PCC = std::pair<const int, const long>; + +int main(int, char**) +{ + { + const PCC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::map m(std::begin(arr), std::end(arr)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, const long>); + const PCC expected_m[] = { {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PCC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::map m(std::begin(arr), std::end(arr), std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, const long, std::greater<int>>); + const PCC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1, 1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PCC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::map m(std::begin(arr), std::end(arr), std::greater<int>(), test_allocator<PCC>(0, 42)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, const long, std::greater<int>, test_allocator<PCC>>); + const PCC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1, 1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 42); + } + + { + std::map m{ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }; + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long>); + const PC expected_m[] = { {1, 1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::greater<int>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1, 1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, std::greater<int>(), test_allocator<PC>(0, 43)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::greater<int>, test_allocator<PC>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1, 1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 43); + } + + { + std::map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, test_allocator<PC>(0, 45)); + + ASSERT_SAME_TYPE(decltype(m), std::map<int, long, std::less<int>, test_allocator<PC>>); + const PC expected_m[] = { {1, 1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + return 0; +} diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.fail.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.fail.cpp new file mode 100644 index 00000000000..70fa2522cc1 --- /dev/null +++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.fail.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <map> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides +// XFAIL: clang-6, apple-clang-9.0, apple-clang-9.1, apple-clang-10.0 +// clang-6 gives different error messages. + +// template<class InputIterator, +// class Compare = less<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// multimap(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> multimap<iter-value-type<InputIterator>, Compare, Allocator>; +// template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> +// multimap(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) +// -> multimap<Key, Compare, Allocator>; +// template<class InputIterator, class Allocator> +// multimap(InputIterator, InputIterator, Allocator) +// -> multimap<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; +// template<class Key, class Allocator> +// multimap(initializer_list<Key>, Allocator) +// -> multimap<Key, less<Key>, Allocator>; + +#include <climits> // INT_MAX +#include <functional> +#include <map> +#include <type_traits> + +struct NotAnAllocator { + friend bool operator<(NotAnAllocator, NotAnAllocator) { return false; } +}; + +using P = std::pair<int, long>; +using PC = std::pair<const int, long>; + +int main(int, char**) +{ + { + // cannot deduce Key and T from nothing + std::multimap m; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // cannot deduce Key and T from just (Compare) + std::multimap m(std::less<int>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // cannot deduce Key and T from just (Compare, Allocator) + std::multimap m(std::less<int>{}, std::allocator<PC>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // cannot deduce Key and T from just (Allocator) + std::multimap m(std::allocator<PC>{}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // refuse to rebind the allocator if Allocator::value_type is not exactly what we expect + const P arr[] = { {1,1L}, {2,2L}, {3,3L} }; + std::multimap m(arr, arr + 3, std::allocator<P>()); + // expected-error-re@map:* {{static_assert failed{{( due to requirement '.*')?}} "Allocator::value_type must be same type as value_type"}} + } + { + // cannot convert from some arbitrary unrelated type + NotAnAllocator a; + std::multimap m(a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::multimap m{ {1,1L}, {2,2L}, {3,3L} }; + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::multimap m({ {1,1L}, {2,2L}, {3,3L} }, std::less<int>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::multimap m({ {1,1L}, {2,2L}, {3,3L} }, std::less<int>(), std::allocator<PC>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // cannot deduce that the inner braced things should be std::pair and not something else + std::multimap m({ {1,1L}, {2,2L}, {3,3L} }, std::allocator<PC>()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // since we have parens, not braces, this deliberately does not find the initializer_list constructor + std::multimap m(P{1,1L}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + // since we have parens, not braces, this deliberately does not find the initializer_list constructor + std::multimap m(PC{1,1L}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + + return 0; +} diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp new file mode 100644 index 00000000000..0a28d7835ea --- /dev/null +++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <map> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Compare = less<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// multimap(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> multimap<iter-value-type<InputIterator>, Compare, Allocator>; +// template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> +// multimap(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) +// -> multimap<Key, Compare, Allocator>; +// template<class InputIterator, class Allocator> +// multimap(InputIterator, InputIterator, Allocator) +// -> multimap<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; +// template<class Key, class Allocator> +// multimap(initializer_list<Key>, Allocator) +// -> multimap<Key, less<Key>, Allocator>; + +#include <algorithm> // std::equal +#include <cassert> +#include <climits> // INT_MAX +#include <functional> +#include <map> +#include <type_traits> + +#include "test_allocator.h" + +using P = std::pair<int, long>; +using PC = std::pair<const int, long>; + +int main(int, char**) +{ + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::multimap m(std::begin(arr), std::end(arr)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long>); + const PC expected_m[] = { {1,1L}, {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::multimap m(std::begin(arr), std::end(arr), std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::greater<int>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::multimap m(std::begin(arr), std::end(arr), std::greater<int>(), test_allocator<PC>(0, 42)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::greater<int>, test_allocator<PC>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 42); + } + + { + std::multimap<int, long> source; + std::multimap m(source); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::multimap<int, long> source; + std::multimap m{source}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::multimap<int, long> source; + std::multimap m(source, std::map<int, long>::allocator_type()); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::multimap m{ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }; + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long>); + const PC expected_m[] = { {1,1L}, {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::greater<int>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, std::greater<int>(), test_allocator<PC>(0, 43)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::greater<int>, test_allocator<PC>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 43); + } + + { + const P arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::multimap m(std::begin(arr), std::end(arr), test_allocator<PC>(0, 44)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::less<int>, test_allocator<PC>>); + const PC expected_m[] = { {1,1L}, {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + std::multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, test_allocator<PC>(0, 45)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::less<int>, test_allocator<PC>>); + const PC expected_m[] = { {1,1L}, {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + return 0; +} diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct_const.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct_const.pass.cpp new file mode 100644 index 00000000000..1c1eb2fd74f --- /dev/null +++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct_const.pass.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <map> +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template<class InputIterator, +// class Compare = less<iter-value-type<InputIterator>>, +// class Allocator = allocator<iter-value-type<InputIterator>>> +// multimap(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> multimap<iter-value-type<InputIterator>, Compare, Allocator>; +// template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> +// multimap(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) +// -> multimap<Key, Compare, Allocator>; +// template<class InputIterator, class Allocator> +// multimap(InputIterator, InputIterator, Allocator) +// -> multimap<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; +// template<class Key, class Allocator> +// multimap(initializer_list<Key>, Allocator) +// -> multimap<Key, less<Key>, Allocator>; + +#include <algorithm> // std::equal +#include <cassert> +#include <climits> // INT_MAX +#include <functional> +#include <map> +#include <type_traits> + +#include "test_allocator.h" + +using P = std::pair<int, long>; +using PC = std::pair<const int, long>; +using PCC = std::pair<const int, const long>; + +int main(int, char**) +{ + { + const PCC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::multimap m(std::begin(arr), std::end(arr)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, const long>); + const PCC expected_m[] = { {1,1L}, {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PCC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::multimap m(std::begin(arr), std::end(arr), std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, const long, std::greater<int>>); + const PCC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PCC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::multimap m(std::begin(arr), std::end(arr), std::greater<int>(), test_allocator<PCC>(0, 42)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, const long, std::greater<int>, test_allocator<PCC>>); + const PCC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 42); + } + + { + std::multimap m{ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }; + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long>); + const PC expected_m[] = { {1,1L}, {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, std::greater<int>()); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::greater<int>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, std::greater<int>(), test_allocator<PC>(0, 43)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::greater<int>, test_allocator<PC>>); + const PC expected_m[] = { {INT_MAX,1L}, {3,1L}, {2,2L}, {1,1L}, {1,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 43); + } + + { + std::multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, test_allocator<PC>(0, 45)); + + ASSERT_SAME_TYPE(decltype(m), std::multimap<int, long, std::less<int>, test_allocator<PC>>); + const PC expected_m[] = { {1,1L}, {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + return 0; +} |