Index: include/iterator =================================================================== --- include/iterator +++ include/iterator @@ -533,6 +533,22 @@ __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 +using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; + +template +using __iter_key_type = remove_const_t::value_type::first_type>; + +template +using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; + +template +using __iter_to_alloc_type = pair< + add_const_t::value_type::first_type>, + typename iterator_traits<_InputIterator>::value_type::second_type>; +#endif + template struct _LIBCPP_TEMPLATE_VIS iterator Index: include/map =================================================================== --- include/map +++ include/map @@ -1461,6 +1461,32 @@ #endif }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template>, + class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +map(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) + -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; + +template, + class _Allocator = allocator>, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +map(initializer_list>, _Compare = _Compare(), _Allocator = _Allocator()) + -> map<_Key, _Tp, _Compare, _Allocator>; + +template::value, void>::type> +map(_InputIterator, _InputIterator, _Allocator) + -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + less<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value, void>::type> +map(initializer_list>, _Allocator) + -> map<_Key, _Tp, less<_Key>, _Allocator>; +#endif #ifndef _LIBCPP_CXX03_LANG template @@ -2082,6 +2108,33 @@ typedef unique_ptr<__node, _Dp> __node_holder; }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template>, + class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +multimap(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; + +template, + class _Allocator = allocator>, + class = typename enable_if::value, void>::type, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type> +multimap(initializer_list>, _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<_Key, _Tp, _Compare, _Allocator>; + +template::value, void>::type> +multimap(_InputIterator, _InputIterator, _Allocator) + -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + less<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value, void>::type> +multimap(initializer_list>, _Allocator) + -> multimap<_Key, _Tp, less<_Key>, _Allocator>; +#endif + #ifndef _LIBCPP_CXX03_LANG template multimap<_Key, _Tp, _Compare, _Allocator>::multimap(multimap&& __m, const allocator_type& __a) Index: test/std/containers/associative/map/map.cons/deduct.fail.cpp =================================================================== --- /dev/null +++ test/std/containers/associative/map/map.cons/deduct.fail.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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 Allocator = allocator>> +// map(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> map, iter-mapped-type, Compare, Allocator>; +// template, +// class Allocator = allocator>> +// map(initializer_list>, Compare = Compare(), Allocator = Allocator()) +// -> map; +// template +// map(InputIterator, InputIterator, Allocator) +// -> map, iter-mapped-type, +// less>, Allocator>; +// template +// map(initializer_list>, Allocator) -> map, Allocator>; + +#include // INT_MAX +#include +#include + +struct A {}; + +int main(int, char**) +{ + { + A a; + std::map s(a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + std::allocator a; + std::map s(a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + A a; + std::map s(a, a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + A a; + std::map s{a}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + A a; + std::map s{a, a}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + std::map m{ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + std::map m({ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }, std::greater()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + using P = std::pair; + std::map m({ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }, std::greater(), std::allocator

()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + { + using P = std::pair; + std::map m({ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }, std::allocator

()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'map'}} + } + + return 0; +} Index: test/std/containers/associative/map/map.cons/deduct.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/associative/map/map.cons/deduct.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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 Allocator = allocator>> +// map(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> map, Compare, Allocator>; +// template, class Allocator = allocator> +// map(initializer_list, Compare = Compare(), Allocator = Allocator()) +// -> map; +// template +// map(InputIterator, InputIterator, Allocator) +// -> map, less>, Allocator>; +// template +// map(initializer_list, Allocator) -> map, Allocator>; + +#include +#include +#include // INT_MAX + +#include "test_allocator.h" + +struct A { + friend bool operator<(A, A) { return false; } +}; + +int main(int, char**) +{ + +// Test the explicit deduction guides + { + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::map m(std::begin(arr), std::end(arr)); + + static_assert(std::is_same_v>, ""); + std::pair expected_m[] = { {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::map m(std::begin(arr), std::end(arr), std::greater()); + + static_assert(std::is_same_v>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + using P = std::pair; + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::map m(std::begin(arr), std::end(arr), std::greater(), test_allocator

(0, 42)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1} }; + 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{ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }; + + static_assert(std::is_same_v>, ""); + std::pair expected_m[] = { {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::map m({ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }, std::greater()); + + static_assert(std::is_same_v>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + using P = std::pair; + std::map m({ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }, std::greater(), test_allocator

(0, 43)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 43); + } + + { + using P = std::pair; + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::map m(std::begin(arr), std::end(arr), test_allocator

(0, 44)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + using P = std::pair; + std::map m({ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }, test_allocator

(0, 45)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + { + std::map source; + std::map m(source); // map(map &) + static_assert(std::is_same_v>, ""); + assert(m.size() == 0); + } + + { + std::map source; + std::map m{source}; // map(map &) + static_assert(std::is_same_v>, ""); + assert(m.size() == 0); + } + + return 0; +} Index: test/std/containers/associative/multimap/multimap.cons/deduct.fail.cpp =================================================================== --- /dev/null +++ test/std/containers/associative/multimap/multimap.cons/deduct.fail.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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 Allocator = allocator>> +// multimap(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> multimap, iter-multimapped-type, Compare, Allocator>; +// template, +// class Allocator = allocator>> +// multimap(initializer_list>, Compare = Compare(), Allocator = Allocator()) +// -> multimap; +// template +// multimap(InputIterator, InputIterator, Allocator) +// -> multimap, iter-multimapped-type, +// less>, Allocator>; +// template +// multimap(initializer_list>, Allocator) -> multimap, Allocator>; + +#include // INT_MAX +#include +#include + +struct A {}; + +int main(int, char**) +{ + { + A a; + std::multimap s(a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + std::allocator a; + std::multimap s(a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + A a; + std::multimap s(a, a); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + A a; + std::multimap s{a}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + A a; + std::multimap s{a, a}; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + std::multimap m{ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + std::multimap m({ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }, std::greater()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + using P = std::pair; + std::multimap m({ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }, std::greater(), std::allocator

()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + { + using P = std::pair; + std::multimap m({ {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }, std::allocator

()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'multimap'}} + } + + return 0; +} Index: test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp =================================================================== --- /dev/null +++ test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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 Allocator = allocator>> +// multimap(InputIterator, InputIterator, +// Compare = Compare(), Allocator = Allocator()) +// -> multimap, Compare, Allocator>; +// template, class Allocator = allocator> +// multimap(initializer_list, Compare = Compare(), Allocator = Allocator()) +// -> multimap; +// template +// multimap(InputIterator, InputIterator, Allocator) +// -> multimap, less>, Allocator>; +// template +// multimap(initializer_list, Allocator) -> multimap, Allocator>; + +#include +#include +#include // INT_MAX + +#include "test_allocator.h" + +struct A { + friend bool operator<(A, A) { return false; } +}; + +int main(int, char**) +{ + +// Test the explicit deduction guides + { + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::multimap m(std::begin(arr), std::end(arr)); + + static_assert(std::is_same_v>, ""); + std::pair expected_m[] = { {1,1}, {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::multimap m(std::begin(arr), std::end(arr), std::greater()); + + static_assert(std::is_same_v>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1}, {1,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + using P = std::pair; + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::multimap m(std::begin(arr), std::end(arr), std::greater(), test_allocator

(0, 42)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1}, {1,1} }; + 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{ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }; + + static_assert(std::is_same_v>, ""); + std::pair expected_m[] = { {1,1}, {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::multimap m({ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }, std::greater()); + + static_assert(std::is_same_v>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1}, {1,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + using P = std::pair; + std::multimap m({ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }, std::greater(), test_allocator

(0, 43)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {INT_MAX,1}, {3,1}, {2,2}, {1,1}, {1,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 43); + } + + { + using P = std::pair; + const std::pair arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::multimap m(std::begin(arr), std::end(arr), test_allocator

(0, 44)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {1,1}, {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + using P = std::pair; + std::multimap m({ std::pair{1,1}, std::pair{2,2}, std::pair{1,1}, std::pair{INT_MAX,1}, std::pair{3,1} }, test_allocator

(0, 45)); + + static_assert(std::is_same_v, test_allocator

>>, ""); + std::pair expected_m[] = { {1,1}, {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + assert(std::equal(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + { + std::multimap source; + std::multimap m(source); // multimap(multimap &) + static_assert(std::is_same_v>, ""); + assert(m.size() == 0); + } + + { + std::multimap source; + std::multimap m{source}; // multimap(multimap &) + static_assert(std::is_same_v>, ""); + assert(m.size() == 0); + } + + return 0; +}