This implements the C++23 P1518R2 proposal "Stop overconstraining allocators in container deduction guides" as a fix for C++17 and C++20 too.
The changes allow class template argument deduction to ignore the type of a constructor argument that initializes an allocator_type parameter if the type should be deducible only from the other arguments. So for the constructor vector(const vector&, const allocator_type&) only the first argument is used for deduction, allowing the second argument to be anything that is implicitly convertible to argument_type. Previously deduction would fail or an ill-formed type would be deduced if the second argument wasn't of type allocator_type. The unordered containers do not need changes, because their allocator-extended constructors use the allocator_type alias, which comes from the dependent base class so is already a non-deduced context. libstdc++-v3/ChangeLog: * include/bits/forward_list.h (forward_list): Use non-deduced context for allocator parameter of allocator-extended copy and move constructors. * include/bits/stl_bvector.h (vector<bool>): Likewise. * include/bits/stl_deque.h (deque): Likewise. * include/bits/stl_list.h (list): Likewise. * include/bits/stl_map.h (map): Likewise. * include/bits/stl_multimap.h (multimap): Likewise. * include/bits/stl_multiset.h (multiset): Likewise. * include/bits/stl_set.h (set): Likewise. * include/bits/stl_vector.h (vector): Likewise. * include/bits/stl_queue.h (queue, priority_queue): Do not constrain Allocator template parameter of deduction guides that have a Container parameter. * include/bits/stl_stack.h (stack): Likewise. * include/debug/deque (__gnu_debug::deque): Use non-deduced context for allocator parameter of allocator-extended copy and move constructors. * include/debug/list (__gnu_debug::list): Likewise. * include/debug/map.h (__gnu_debug::map): Likewise. * include/debug/multimap.h (__gnu_debug::multimap): Likewise. * include/debug/multiset.h (__gnu_debug::multiset): Likewise. * include/debug/set.h (__gnu_debug::set): Likewise. * include/debug/vector (__gnu_debug::vector): Likewise. * testsuite/23_containers/deque/cons/deduction.cc: Test class template argument deduction with non-deduced allocator arguments. * testsuite/23_containers/forward_list/cons/deduction.cc: Likewise. * testsuite/23_containers/list/cons/deduction.cc: Likewise. * testsuite/23_containers/map/cons/deduction.cc: Likewise. * testsuite/23_containers/multimap/cons/deduction.cc: Likewise. * testsuite/23_containers/multiset/cons/deduction.cc: Likewise. * testsuite/23_containers/priority_queue/deduction.cc: Likewise. * testsuite/23_containers/queue/deduction.cc: Likewise. * testsuite/23_containers/set/cons/deduction.cc: Likewise. * testsuite/23_containers/stack/deduction.cc: Likewise. * testsuite/23_containers/unordered_map/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_multimap/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_multiset/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_set/cons/deduction.cc: Likewise. * testsuite/23_containers/vector/cons/deduction.cc: Likewise. Tested powerpc64le-linux. Committed to trunk.
commit 22d34a2a50651d01669b6fbcdb9677c18d2197c5 Author: Jonathan Wakely <jwak...@redhat.com> Date: Mon Oct 4 14:04:20 2021 libstdc++: Implement P1518R2 for container deduction guides This implements the C++23 P1518R2 proposal "Stop overconstraining allocators in container deduction guides" as a fix for C++17 and C++20 too. The changes allow class template argument deduction to ignore the type of a constructor argument that initializes an allocator_type parameter if the type should be deducible only from the other arguments. So for the constructor vector(const vector&, const allocator_type&) only the first argument is used for deduction, allowing the second argument to be anything that is implicitly convertible to argument_type. Previously deduction would fail or an ill-formed type would be deduced if the second argument wasn't of type allocator_type. The unordered containers do not need changes, because their allocator-extended constructors use the allocator_type alias, which comes from the dependent base class so is already a non-deduced context. libstdc++-v3/ChangeLog: * include/bits/forward_list.h (forward_list): Use non-deduced context for allocator parameter of allocator-extended copy and move constructors. * include/bits/stl_bvector.h (vector<bool>): Likewise. * include/bits/stl_deque.h (deque): Likewise. * include/bits/stl_list.h (list): Likewise. * include/bits/stl_map.h (map): Likewise. * include/bits/stl_multimap.h (multimap): Likewise. * include/bits/stl_multiset.h (multiset): Likewise. * include/bits/stl_set.h (set): Likewise. * include/bits/stl_vector.h (vector): Likewise. * include/bits/stl_queue.h (queue, priority_queue): Do not constrain Allocator template parameter of deduction guides that have a Container parameter. * include/bits/stl_stack.h (stack): Likewise. * include/debug/deque (__gnu_debug::deque): Use non-deduced context for allocator parameter of allocator-extended copy and move constructors. * include/debug/list (__gnu_debug::list): Likewise. * include/debug/map.h (__gnu_debug::map): Likewise. * include/debug/multimap.h (__gnu_debug::multimap): Likewise. * include/debug/multiset.h (__gnu_debug::multiset): Likewise. * include/debug/set.h (__gnu_debug::set): Likewise. * include/debug/vector (__gnu_debug::vector): Likewise. * testsuite/23_containers/deque/cons/deduction.cc: Test class template argument deduction with non-deduced allocator arguments. * testsuite/23_containers/forward_list/cons/deduction.cc: Likewise. * testsuite/23_containers/list/cons/deduction.cc: Likewise. * testsuite/23_containers/map/cons/deduction.cc: Likewise. * testsuite/23_containers/multimap/cons/deduction.cc: Likewise. * testsuite/23_containers/multiset/cons/deduction.cc: Likewise. * testsuite/23_containers/priority_queue/deduction.cc: Likewise. * testsuite/23_containers/queue/deduction.cc: Likewise. * testsuite/23_containers/set/cons/deduction.cc: Likewise. * testsuite/23_containers/stack/deduction.cc: Likewise. * testsuite/23_containers/unordered_map/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_multimap/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_multiset/cons/deduction.cc: Likewise. * testsuite/23_containers/unordered_set/cons/deduction.cc: Likewise. * testsuite/23_containers/vector/cons/deduction.cc: Likewise. diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index ab6d9389194..aa8623b4c19 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -480,7 +480,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __list Input list to copy. * @param __al An allocator object. */ - forward_list(const forward_list& __list, const _Alloc& __al) + forward_list(const forward_list& __list, + const __type_identity_t<_Alloc>& __al) : _Base(_Node_alloc_type(__al)) { _M_range_initialize(__list.begin(), __list.end()); } @@ -508,7 +509,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __list Input list to move. * @param __al An allocator object. */ - forward_list(forward_list&& __list, const _Alloc& __al) + forward_list(forward_list&& __list, + const __type_identity_t<_Alloc>& __al) noexcept(_Node_alloc_traits::_S_always_equal()) : forward_list(std::move(__list), _Node_alloc_type(__al), typename _Node_alloc_traits::is_always_equal{}) diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index a954890ff20..3778d5a770a 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -706,13 +706,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } public: - vector(vector&& __x, const allocator_type& __a) + vector(vector&& __x, const __type_identity_t<allocator_type>& __a) noexcept(_Bit_alloc_traits::_S_always_equal()) : vector(std::move(__x), __a, typename _Bit_alloc_traits::is_always_equal{}) { } - vector(const vector& __x, const allocator_type& __a) + vector(const vector& __x, const __type_identity_t<allocator_type>& __a) : _Base(__a) { _M_initialize(__x.size()); diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index 6095498d440..268fb9ef405 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -932,14 +932,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER deque(deque&&) = default; /// Copy constructor with alternative allocator - deque(const deque& __x, const allocator_type& __a) + deque(const deque& __x, const __type_identity_t<allocator_type>& __a) : _Base(__a, __x.size()) { std::__uninitialized_copy_a(__x.begin(), __x.end(), this->_M_impl._M_start, _M_get_Tp_allocator()); } /// Move constructor with alternative allocator - deque(deque&& __x, const allocator_type& __a) + deque(deque&& __x, const __type_identity_t<allocator_type>& __a) : deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{}) { } diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index 81361dfa4d5..96d2a2f0f69 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -836,7 +836,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 : _Base(_Node_alloc_type(__a)) { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); } - list(const list& __x, const allocator_type& __a) + list(const list& __x, const __type_identity_t<allocator_type>& __a) : _Base(_Node_alloc_type(__a)) { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } @@ -856,7 +856,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } public: - list(list&& __x, const allocator_type& __a) + list(list&& __x, const __type_identity_t<allocator_type>& __a) noexcept(_Node_alloc_traits::_S_always_equal()) : list(std::move(__x), __a, typename _Node_alloc_traits::is_always_equal{}) diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index 535dbeb745a..cc87f11fb11 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -237,11 +237,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _M_t(_Pair_alloc_type(__a)) { } /// Allocator-extended copy constructor. - map(const map& __m, const allocator_type& __a) + map(const map& __m, const __type_identity_t<allocator_type>& __a) : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } /// Allocator-extended move constructor. - map(map&& __m, const allocator_type& __a) + map(map&& __m, const __type_identity_t<allocator_type>& __a) noexcept(is_nothrow_copy_constructible<_Compare>::value && _Alloc_traits::_S_always_equal()) : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index 8157981d0bc..1b9648e3bd4 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -234,11 +234,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _M_t(_Pair_alloc_type(__a)) { } /// Allocator-extended copy constructor. - multimap(const multimap& __m, const allocator_type& __a) + multimap(const multimap& __m, + const __type_identity_t<allocator_type>& __a) : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } /// Allocator-extended move constructor. - multimap(multimap&& __m, const allocator_type& __a) + multimap(multimap&& __m, const __type_identity_t<allocator_type>& __a) noexcept(is_nothrow_copy_constructible<_Compare>::value && _Alloc_traits::_S_always_equal()) : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h index ef987600733..5d9d6195ae1 100644 --- a/libstdc++-v3/include/bits/stl_multiset.h +++ b/libstdc++-v3/include/bits/stl_multiset.h @@ -248,11 +248,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _M_t(_Key_alloc_type(__a)) { } /// Allocator-extended copy constructor. - multiset(const multiset& __m, const allocator_type& __a) + multiset(const multiset& __m, + const __type_identity_t<allocator_type>& __a) : _M_t(__m._M_t, _Key_alloc_type(__a)) { } /// Allocator-extended move constructor. - multiset(multiset&& __m, const allocator_type& __a) + multiset(multiset&& __m, const __type_identity_t<allocator_type>& __a) noexcept(is_nothrow_copy_constructible<_Compare>::value && _Alloc_traits::_S_always_equal()) : _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { } diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h index ccd1122f848..3da65c78eb8 100644 --- a/libstdc++-v3/include/bits/stl_queue.h +++ b/libstdc++-v3/include/bits/stl_queue.h @@ -342,8 +342,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION queue(_Container) -> queue<typename _Container::value_type, _Container>; template<typename _Container, typename _Allocator, - typename = _RequireNotAllocator<_Container>, - typename = _RequireAllocator<_Allocator>> + typename = _RequireNotAllocator<_Container>> queue(_Container, _Allocator) -> queue<typename _Container::value_type, _Container>; @@ -817,8 +816,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Compare, typename _Container, typename _Allocator, typename = _RequireNotAllocator<_Compare>, - typename = _RequireNotAllocator<_Container>, - typename = _RequireAllocator<_Allocator>> + typename = _RequireNotAllocator<_Container>> priority_queue(_Compare, _Container, _Allocator) -> priority_queue<typename _Container::value_type, _Container, _Compare>; #endif diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h index a9b9695bca8..f0dfa05886f 100644 --- a/libstdc++-v3/include/bits/stl_set.h +++ b/libstdc++-v3/include/bits/stl_set.h @@ -252,11 +252,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _M_t(_Key_alloc_type(__a)) { } /// Allocator-extended copy constructor. - set(const set& __x, const allocator_type& __a) + set(const set& __x, const __type_identity_t<allocator_type>& __a) : _M_t(__x._M_t, _Key_alloc_type(__a)) { } /// Allocator-extended move constructor. - set(set&& __x, const allocator_type& __a) + set(set&& __x, const __type_identity_t<allocator_type>& __a) noexcept(is_nothrow_copy_constructible<_Compare>::value && _Alloc_traits::_S_always_equal()) : _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { } diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h index af234d6899c..f04fa6af479 100644 --- a/libstdc++-v3/include/bits/stl_stack.h +++ b/libstdc++-v3/include/bits/stl_stack.h @@ -317,8 +317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION stack(_Container) -> stack<typename _Container::value_type, _Container>; template<typename _Container, typename _Allocator, - typename = _RequireNotAllocator<_Container>, - typename = _RequireAllocator<_Allocator>> + typename = _RequireNotAllocator<_Container>> stack(_Container, _Allocator) -> stack<typename _Container::value_type, _Container>; diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 296da43822a..2023581bc79 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -572,7 +572,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector(vector&&) noexcept = default; /// Copy constructor with alternative allocator - vector(const vector& __x, const allocator_type& __a) + vector(const vector& __x, const __type_identity_t<allocator_type>& __a) : _Base(__x.size(), __a) { this->_M_impl._M_finish = @@ -604,7 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER public: /// Move constructor with alternative allocator - vector(vector&& __rv, const allocator_type& __m) + vector(vector&& __rv, const __type_identity_t<allocator_type>& __m) noexcept( noexcept( vector(std::declval<vector&&>(), std::declval<const allocator_type&>(), std::declval<typename _Alloc_traits::is_always_equal>())) ) diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque index 574cab11c6f..8e4811149d2 100644 --- a/libstdc++-v3/include/debug/deque +++ b/libstdc++-v3/include/debug/deque @@ -108,10 +108,10 @@ namespace __debug deque(const deque&) = default; deque(deque&&) = default; - deque(const deque& __d, const _Allocator& __a) + deque(const deque& __d, const __type_identity_t<_Allocator>& __a) : _Base(__d, __a) { } - deque(deque&& __d, const _Allocator& __a) + deque(deque&& __d, const __type_identity_t<_Allocator>& __a) : _Safe(std::move(__d)), _Base(std::move(__d), __a) { } deque(initializer_list<value_type> __l, diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list index b599e93d147..de30edb19c2 100644 --- a/libstdc++-v3/include/debug/list +++ b/libstdc++-v3/include/debug/list @@ -115,10 +115,10 @@ namespace __debug ~list() = default; - list(const list& __x, const allocator_type& __a) + list(const list& __x, const __type_identity_t<allocator_type>& __a) : _Base(__x, __a) { } - list(list&& __x, const allocator_type& __a) + list(list&& __x, const __type_identity_t<allocator_type>& __a) noexcept( std::is_nothrow_constructible<_Base, _Base, const allocator_type&>::value ) diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h index c0153d09abe..9e142cf7023 100644 --- a/libstdc++-v3/include/debug/map.h +++ b/libstdc++-v3/include/debug/map.h @@ -114,10 +114,10 @@ namespace __debug map(const allocator_type& __a) : _Base(__a) { } - map(const map& __m, const allocator_type& __a) + map(const map& __m, const __type_identity_t<allocator_type>& __a) : _Base(__m, __a) { } - map(map&& __m, const allocator_type& __a) + map(map&& __m, const __type_identity_t<allocator_type>& __a) noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) ) : _Safe(std::move(__m._M_safe()), __a), _Base(std::move(__m._M_base()), __a) { } diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h index 94929344a9d..a05b8a8493e 100644 --- a/libstdc++-v3/include/debug/multimap.h +++ b/libstdc++-v3/include/debug/multimap.h @@ -114,10 +114,11 @@ namespace __debug multimap(const allocator_type& __a) : _Base(__a) { } - multimap(const multimap& __m, const allocator_type& __a) + multimap(const multimap& __m, + const __type_identity_t<allocator_type>& __a) : _Base(__m, __a) { } - multimap(multimap&& __m, const allocator_type& __a) + multimap(multimap&& __m, const __type_identity_t<allocator_type>& __a) noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) ) : _Safe(std::move(__m._M_safe()), __a), _Base(std::move(__m._M_base()), __a) { } diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h index bb68d8c8f18..a312ccf6f50 100644 --- a/libstdc++-v3/include/debug/multiset.h +++ b/libstdc++-v3/include/debug/multiset.h @@ -113,10 +113,11 @@ namespace __debug multiset(const allocator_type& __a) : _Base(__a) { } - multiset(const multiset& __m, const allocator_type& __a) + multiset(const multiset& __m, + const __type_identity_t<allocator_type>& __a) : _Base(__m, __a) { } - multiset(multiset&& __m, const allocator_type& __a) + multiset(multiset&& __m, const __type_identity_t<allocator_type>& __a) noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) ) : _Safe(std::move(__m._M_safe()), __a), _Base(std::move(__m._M_base()), __a) { } diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h index cdf35ea5396..01da942eb78 100644 --- a/libstdc++-v3/include/debug/set.h +++ b/libstdc++-v3/include/debug/set.h @@ -113,10 +113,10 @@ namespace __debug set(const allocator_type& __a) : _Base(__a) { } - set(const set& __x, const allocator_type& __a) + set(const set& __x, const __type_identity_t<allocator_type>& __a) : _Base(__x, __a) { } - set(set&& __x, const allocator_type& __a) + set(set&& __x, const __type_identity_t<allocator_type>& __a) noexcept( noexcept(_Base(std::move(__x._M_base()), __a)) ) : _Safe(std::move(__x._M_safe()), __a), _Base(std::move(__x._M_base()), __a) { } diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index d30d750a6f0..03fd9405cc9 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -212,10 +212,10 @@ namespace __debug vector(const vector&) = default; vector(vector&&) = default; - vector(const vector& __x, const allocator_type& __a) + vector(const vector& __x, const __type_identity_t<allocator_type>& __a) : _Base(__x, __a) { } - vector(vector&& __x, const allocator_type& __a) + vector(vector&& __x, const __type_identity_t<allocator_type>& __a) noexcept( std::is_nothrow_constructible<_Base, _Base, const allocator_type&>::value ) diff --git a/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc index 8a38351e524..5cb0a58a22c 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/cons/deduction.cc @@ -19,6 +19,7 @@ #include <deque> #include <testsuite_iterators.h> +#include <testsuite_allocator.h> template<typename T> using input_iterator_seq @@ -67,3 +68,31 @@ test02() std::deque s4(1U, 2L, std::allocator<long>()); check_type<std::deque<long>>(s4); } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Deque = std::deque<unsigned, Alloc<unsigned>>; + Pool* p = nullptr; + Deque d(p); + + std::deque s1(d, p); + check_type<Deque>(s1); + + std::deque s2(std::move(d), p); + check_type<Deque>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc index eb39682f483..701231d1259 100644 --- a/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/deduction.cc @@ -19,6 +19,7 @@ #include <forward_list> #include <testsuite_iterators.h> +#include <testsuite_allocator.h> template<typename T> using input_iterator_seq @@ -67,3 +68,31 @@ test02() std::forward_list s4(1U, 2L, std::allocator<long>()); check_type<std::forward_list<long>>(s4); } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Flist = std::forward_list<unsigned, Alloc<unsigned>>; + Pool* p = nullptr; + Flist f(p); + + std::forward_list s1(f, p); + check_type<Flist>(s1); + + std::forward_list s2(std::move(f), p); + check_type<Flist>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc index 3ad1d3f6cb5..c747509ffc5 100644 --- a/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/list/cons/deduction.cc @@ -19,6 +19,7 @@ #include <list> #include <testsuite_iterators.h> +#include <testsuite_allocator.h> template<typename T> using input_iterator_seq @@ -67,3 +68,31 @@ test02() std::list s4(1U, 2L, std::allocator<long>()); check_type<std::list<long>>(s4); } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using List = std::list<unsigned, Alloc<unsigned>>; + Pool* p = nullptr; + List l(p); + + std::list s1(l, p); + check_type<List>(s1); + + std::list s2(std::move(l), p); + check_type<List>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc index e72033c38a6..f8e6e6e8b99 100644 --- a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc @@ -222,3 +222,39 @@ void h() std::map<int, double, std::less<int>, SimpleAllocator<value_type>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using PairAlloc = Alloc<std::pair<const unsigned, void*>>; + using Map = std::map<unsigned, void*, std::greater<>, PairAlloc>; + Pool* p = nullptr; + Map m(p); + + std::map s1(m, p); + check_type<Map>(s1); + + std::map s2(std::move(m), p); + check_type<Map>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc index ffc7502d60c..f0699e2eefc 100644 --- a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc @@ -174,3 +174,39 @@ void h() std::multimap<int, double, std::less<int>, SimpleAllocator<value_type>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using PairAlloc = Alloc<std::pair<const unsigned, void*>>; + using MMap = std::multimap<unsigned, void*, std::greater<>, PairAlloc>; + Pool* p = nullptr; + MMap m(p); + + std::multimap s1(m, p); + check_type<MMap>(s1); + + std::multimap s2(std::move(m), p); + check_type<MMap>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc index 8b7a16042a4..7f4581a6aeb 100644 --- a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc @@ -130,3 +130,38 @@ void g() std::multiset<int, std::less<int>, SimpleAllocator<value_type>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using MSet = std::multiset<unsigned, std::greater<>, Alloc<unsigned>>; + Pool* p = nullptr; + MSet s(p); + + std::multiset s1(s, p); + check_type<MSet>(s1); + + std::multiset s2(std::move(s), p); + check_type<MSet>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc index 05c4c570ad5..816efab85c7 100644 --- a/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/priority_queue/deduction.cc @@ -21,6 +21,7 @@ #include <deque> #include <vector> #include <testsuite_iterators.h> +#include <testsuite_allocator.h> template<typename T, typename U> struct require_same; template<typename T> struct require_same<T, T> { using type = void; }; @@ -116,3 +117,39 @@ test02() std::priority_queue s14(seq.begin(), seq.end(), cmp, std::deque<short>{}); check_type<std::priority_queue<short, std::deque<short>, Cmp>>(s14); } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Vector = std::vector<short, Alloc<short>>; + using Cmp = std::greater<long>; + Pool* p = nullptr; + Vector v(p); + Cmp cmp; + + std::priority_queue q1(cmp, v, p); + check_type<std::priority_queue<short, Vector, Cmp>>(q1); + + std::priority_queue q2(cmp, std::move(v), p); + check_type<std::priority_queue<short, Vector, Cmp>>(q2); + + std::priority_queue q3(q1, p); + check_type<std::priority_queue<short, Vector, Cmp>>(q3); + + std::priority_queue q4(std::move(q1), p); + check_type<std::priority_queue<short, Vector, Cmp>>(q4); +} diff --git a/libstdc++-v3/testsuite/23_containers/queue/deduction.cc b/libstdc++-v3/testsuite/23_containers/queue/deduction.cc index ab28f83aa2b..2642ece2b1a 100644 --- a/libstdc++-v3/testsuite/23_containers/queue/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/queue/deduction.cc @@ -20,6 +20,7 @@ #include <queue> #include <deque> #include <list> +#include <testsuite_allocator.h> template<typename T, typename U> struct require_same; template<typename T> struct require_same<T, T> { using type = void; }; @@ -86,3 +87,36 @@ test02() std::queue s8(std::move(l), l.get_allocator()); check_type<std::queue<long, std::list<long>>>(s8); } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Deque = std::deque<unsigned, Alloc<unsigned>>; + using List = std::list<long, Alloc<long>>; + Pool* p = nullptr; + Deque d(p); + List l(p); + + std::queue q1(d, p); + check_type<std::queue<unsigned, Deque>>(q1); + + std::queue q2(l, p); + check_type<std::queue<long, List>>(q2); + + std::queue q3(q2, p); + check_type<std::queue<long, List>>(q3); +} diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc index 14f36b7c05d..d77b9fcb73d 100644 --- a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc @@ -131,3 +131,38 @@ void g() std::set<int, std::less<int>, SimpleAllocator<value_type>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Set = std::set<unsigned, std::greater<>, Alloc<unsigned>>; + Pool* p = nullptr; + Set s(p); + + std::set s1(s, p); + check_type<Set>(s1); + + std::set s2(std::move(s), p); + check_type<Set>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/stack/deduction.cc b/libstdc++-v3/testsuite/23_containers/stack/deduction.cc index db8e31e2bda..169a063687b 100644 --- a/libstdc++-v3/testsuite/23_containers/stack/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/stack/deduction.cc @@ -20,6 +20,7 @@ #include <stack> #include <deque> #include <list> +#include <testsuite_allocator.h> template<typename T, typename U> struct require_same; template<typename T> struct require_same<T, T> { using type = void; }; @@ -58,7 +59,7 @@ test01() void test02() - { +{ std::deque<unsigned> d; std::list<long> l; diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc index 0785447a81b..8b69af896a2 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc @@ -124,3 +124,41 @@ void f() std::equal_to<int>, SimpleAllocator<std::pair<const int, double>>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using PairAlloc = Alloc<std::pair<const unsigned, void*>>; + using Hash = std::hash<unsigned long>; + using Eq = std::equal_to<>; + using UMap = std::unordered_map<unsigned, void*, Hash, Eq, PairAlloc>; + Pool* p = nullptr; + UMap m(p); + + std::unordered_map s1(m, p); + check_type<UMap>(s1); + + std::unordered_map s2(std::move(m), p); + check_type<UMap>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc index d8a6f5136c9..e7e535b527a 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc @@ -133,3 +133,41 @@ void f() std::equal_to<int>, SimpleAllocator<std::pair<const int, double>>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using PairAlloc = Alloc<std::pair<const unsigned, void*>>; + using Hash = std::hash<unsigned long>; + using Eq = std::equal_to<>; + using UMMap = std::unordered_multimap<unsigned, void*, Hash, Eq, PairAlloc>; + Pool* p = nullptr; + UMMap m(p); + + std::unordered_multimap s1(m, p); + check_type<UMMap>(s1); + + std::unordered_multimap s2(std::move(m), p); + check_type<UMMap>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc index 25c2715ea26..22b729749e2 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc @@ -142,3 +142,40 @@ void f() std::equal_to<int>, SimpleAllocator<int>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Hash = std::hash<unsigned long>; + using Eq = std::equal_to<>; + using UMSet = std::unordered_multiset<unsigned, Hash, Eq, Alloc<unsigned>>; + Pool* p = nullptr; + UMSet s(p); + + std::unordered_multiset s1(s, p); + check_type<UMSet>(s1); + + std::unordered_multiset s2(std::move(s), p); + check_type<UMSet>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc index b8c45d2993d..db5858132fc 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc @@ -137,3 +137,40 @@ void f() std::equal_to<int>, SimpleAllocator<int>>>); } + +template<typename T, typename U> struct require_same; +template<typename T> struct require_same<T, T> { using type = void; }; + +template<typename T, typename U> + typename require_same<T, U>::type + check_type(U&) { } + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Hash = std::hash<unsigned long>; + using Eq = std::equal_to<>; + using USet = std::unordered_set<unsigned, Hash, Eq, Alloc<unsigned>>; + Pool* p = nullptr; + USet s(p); + + std::unordered_set s1(s, p); + check_type<USet>(s1); + + std::unordered_set s2(std::move(s), p); + check_type<USet>(s2); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc index 9f7b7612c93..542a0d7ff93 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/deduction.cc @@ -19,6 +19,7 @@ #include <vector> #include <testsuite_iterators.h> +#include <testsuite_allocator.h> template<typename T> using input_iterator_seq @@ -49,6 +50,24 @@ test01() check_type<const std::vector<unsigned>>(s4); } +void +test01b() +{ + std::vector<bool> s0; + + std::vector s1 = s0; + check_type<std::vector<bool>>(s1); + + std::vector s2 = std::move(s0); + check_type<std::vector<bool>>(s2); + + const std::vector s3 = s0; + check_type<const std::vector<bool>>(s3); + + const std::vector s4 = s3; + check_type<const std::vector<bool>>(s4); +} + void test02() { @@ -67,3 +86,59 @@ test02() std::vector s4(1U, 2L, std::allocator<long>()); check_type<std::vector<long>>(s4); } + +void +test02b() +{ + bool a[1] = {}; + input_iterator_seq<bool> seq(a); + + std::vector s1(seq.begin(), seq.end()); + check_type<std::vector<bool>>(s1); + + std::vector s2(seq.begin(), seq.end(), std::allocator<bool>()); + check_type<std::vector<bool>>(s2); + + std::vector s3(1U, true); + check_type<std::vector<bool>>(s3); + + std::vector s4(1U, true, std::allocator<bool>()); + check_type<std::vector<bool>>(s4); +} + +struct Pool; + +template<typename T> +struct Alloc : __gnu_test::SimpleAllocator<T> +{ + Alloc(Pool*) { } + + template<typename U> + Alloc(const Alloc<U>&) { } +}; + +void +test_p1518r2() +{ + // P1518R2 - Stop overconstraining allocators in container deduction guides. + // This is a C++23 feature but we support it for C++17 too. + + using Vector = std::vector<unsigned, Alloc<unsigned>>; + Pool* p = nullptr; + Vector v(p); + + std::vector s1(v, p); + check_type<Vector>(s1); + + std::vector s2(std::move(v), p); + check_type<Vector>(s2); + + using BVector = std::vector<bool, Alloc<bool>>; + BVector b(p); + + std::vector s3(b, p); + check_type<BVector>(s3); + + std::vector s4(std::move(b), p); + check_type<BVector>(s4); +}