[libcxx-commits] [libcxx] dd15c27 - [libc++] [P1518R2] Better CTAD behavior for containers with allocators.
Arthur O'Dwyer via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jun 18 12:55:41 PDT 2021
Author: Arthur O'Dwyer
Date: 2021-06-18T15:54:46-04:00
New Revision: dd15c2723cd29574c341ec189409a6c83fbefb04
URL: https://github.com/llvm/llvm-project/commit/dd15c2723cd29574c341ec189409a6c83fbefb04
DIFF: https://github.com/llvm/llvm-project/commit/dd15c2723cd29574c341ec189409a6c83fbefb04.diff
LOG: [libc++] [P1518R2] Better CTAD behavior for containers with allocators.
P1518 does the following in C++23 but we'll just do it in C++17 as well:
- Stop requiring `Alloc` to be an allocator on some container-adaptor deduction guides
- Stop deducing from `Allocator` on some sequence container constructors
- Stop deducing from `Allocator` on some other container constructors (libc++ already did this)
The affected constructors are the "allocator-extended" versions of
constructors where the non-allocator arguments are already sufficient
to deduce the allocator type. For example,
std::pmr::vector<int> v1;
std::vector v2(v1, std::pmr::new_delete_resource());
std::stack s2(v1, std::pmr::new_delete_resource());
Differential Revision: https://reviews.llvm.org/D97742
Added:
Modified:
libcxx/docs/Cxx2bStatusPaperStatus.csv
libcxx/include/deque
libcxx/include/forward_list
libcxx/include/list
libcxx/include/queue
libcxx/include/stack
libcxx/include/vector
libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Cxx2bStatusPaperStatus.csv b/libcxx/docs/Cxx2bStatusPaperStatus.csv
index 9cbd990b0bb94..8905486bb257f 100644
--- a/libcxx/docs/Cxx2bStatusPaperStatus.csv
+++ b/libcxx/docs/Cxx2bStatusPaperStatus.csv
@@ -11,3 +11,5 @@
"`P2212R2 <https://wg21.link/P2212R2>`__","LWG","Relax Requirements for time_point::clock","February 2021","",""
"`P2259R1 <https://wg21.link/P2259R1>`__","LWG","Repairing input range adaptors and counted_iterator","February 2021","",""
"","","","","",""
+"`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0"
+"","","","","",""
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 4780a24d3837a..526a1c83c6d00 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1317,7 +1317,7 @@ public:
deque(_InputIter __f, _InputIter __l, const allocator_type& __a,
typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0);
deque(const deque& __c);
- deque(const deque& __c, const allocator_type& __a);
+ deque(const deque& __c, const __identity_t<allocator_type>& __a);
deque& operator=(const deque& __c);
@@ -1331,7 +1331,7 @@ public:
_LIBCPP_INLINE_VISIBILITY
deque(deque&& __c) _NOEXCEPT_(is_nothrow_move_constructible<__base>::value);
_LIBCPP_INLINE_VISIBILITY
- deque(deque&& __c, const allocator_type& __a);
+ deque(deque&& __c, const __identity_t<allocator_type>& __a);
_LIBCPP_INLINE_VISIBILITY
deque& operator=(deque&& __c)
_NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value &&
@@ -1660,7 +1660,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c)
}
template <class _Tp, class _Allocator>
-deque<_Tp, _Allocator>::deque(const deque& __c, const allocator_type& __a)
+deque<_Tp, _Allocator>::deque(const deque& __c, const __identity_t<allocator_type>& __a)
: __base(__a)
{
__append(__c.begin(), __c.end());
@@ -1703,7 +1703,7 @@ deque<_Tp, _Allocator>::deque(deque&& __c)
template <class _Tp, class _Allocator>
inline
-deque<_Tp, _Allocator>::deque(deque&& __c, const allocator_type& __a)
+deque<_Tp, _Allocator>::deque(deque&& __c, const __identity_t<allocator_type>& __a)
: __base(_VSTD::move(__c), __a)
{
if (__a != __c.__alloc())
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 66bb449d9f759..086e8ef4ca6ae 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -681,7 +681,7 @@ public:
__is_cpp17_input_iterator<_InputIterator>::value
>::type* = nullptr);
forward_list(const forward_list& __x);
- forward_list(const forward_list& __x, const allocator_type& __a);
+ forward_list(const forward_list& __x, const __identity_t<allocator_type>& __a);
forward_list& operator=(const forward_list& __x);
@@ -690,7 +690,7 @@ public:
forward_list(forward_list&& __x)
_NOEXCEPT_(is_nothrow_move_constructible<base>::value)
: base(_VSTD::move(__x)) {}
- forward_list(forward_list&& __x, const allocator_type& __a);
+ forward_list(forward_list&& __x, const __identity_t<allocator_type>& __a);
forward_list(initializer_list<value_type> __il);
forward_list(initializer_list<value_type> __il, const allocator_type& __a);
@@ -979,7 +979,7 @@ forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x)
template <class _Tp, class _Alloc>
forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x,
- const allocator_type& __a)
+ const __identity_t<allocator_type>& __a)
: base(__a)
{
insert_after(cbefore_begin(), __x.begin(), __x.end());
@@ -1000,7 +1000,7 @@ forward_list<_Tp, _Alloc>::operator=(const forward_list& __x)
#ifndef _LIBCPP_CXX03_LANG
template <class _Tp, class _Alloc>
forward_list<_Tp, _Alloc>::forward_list(forward_list&& __x,
- const allocator_type& __a)
+ const __identity_t<allocator_type>& __a)
: base(_VSTD::move(__x), __a)
{
if (base::__alloc() != __x.__alloc())
diff --git a/libcxx/include/list b/libcxx/include/list
index 439b53398b8f6..f5980570901ad 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -893,7 +893,7 @@ public:
typename enable_if<__is_cpp17_input_iterator<_InpIter>::value>::type* = 0);
list(const list& __c);
- list(const list& __c, const allocator_type& __a);
+ list(const list& __c, const __identity_t<allocator_type>& __a);
_LIBCPP_INLINE_VISIBILITY
list& operator=(const list& __c);
#ifndef _LIBCPP_CXX03_LANG
@@ -904,7 +904,7 @@ public:
list(list&& __c)
_NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value);
_LIBCPP_INLINE_VISIBILITY
- list(list&& __c, const allocator_type& __a);
+ list(list&& __c, const __identity_t<allocator_type>& __a);
_LIBCPP_INLINE_VISIBILITY
list& operator=(list&& __c)
_NOEXCEPT_(
@@ -1286,7 +1286,7 @@ list<_Tp, _Alloc>::list(const list& __c)
}
template <class _Tp, class _Alloc>
-list<_Tp, _Alloc>::list(const list& __c, const allocator_type& __a)
+list<_Tp, _Alloc>::list(const list& __c, const __identity_t<allocator_type>& __a)
: base(__a)
{
#if _LIBCPP_DEBUG_LEVEL == 2
@@ -1333,7 +1333,7 @@ inline list<_Tp, _Alloc>::list(list&& __c)
template <class _Tp, class _Alloc>
inline
-list<_Tp, _Alloc>::list(list&& __c, const allocator_type& __a)
+list<_Tp, _Alloc>::list(list&& __c, const __identity_t<allocator_type>& __a)
: base(__a)
{
#if _LIBCPP_DEBUG_LEVEL == 2
diff --git a/libcxx/include/queue b/libcxx/include/queue
index cc9aa874efe0a..9470a75102a67 100644
--- a/libcxx/include/queue
+++ b/libcxx/include/queue
@@ -339,7 +339,7 @@ queue(_Container)
template<class _Container,
class _Alloc,
class = _EnableIf<!__is_allocator<_Container>::value>,
- class = _EnableIf<__is_allocator<_Alloc>::value>
+ class = _EnableIf<uses_allocator<_Container, _Alloc>::value>
>
queue(_Container, _Alloc)
-> queue<typename _Container::value_type, _Container>;
@@ -554,7 +554,7 @@ template<class _Compare,
class _Alloc,
class = _EnableIf<!__is_allocator<_Compare>::value>,
class = _EnableIf<!__is_allocator<_Container>::value>,
- class = _EnableIf<__is_allocator<_Alloc>::value>
+ class = _EnableIf<uses_allocator<_Container, _Alloc>::value>
>
priority_queue(_Compare, _Container, _Alloc)
-> priority_queue<typename _Container::value_type, _Container, _Compare>;
diff --git a/libcxx/include/stack b/libcxx/include/stack
index a45b979dea9c5..c1b2cbeafa07d 100644
--- a/libcxx/include/stack
+++ b/libcxx/include/stack
@@ -239,7 +239,7 @@ stack(_Container)
template<class _Container,
class _Alloc,
class = _EnableIf<!__is_allocator<_Container>::value>,
- class = _EnableIf<__is_allocator<_Alloc>::value>
+ class = _EnableIf<uses_allocator<_Container, _Alloc>::value>
>
stack(_Container, _Alloc)
-> stack<typename _Container::value_type, _Container>;
diff --git a/libcxx/include/vector b/libcxx/include/vector
index f75a1694910fe..95ef4391806af 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -557,7 +557,7 @@ public:
}
vector(const vector& __x);
- vector(const vector& __x, const allocator_type& __a);
+ vector(const vector& __x, const __identity_t<allocator_type>& __a);
_LIBCPP_INLINE_VISIBILITY
vector& operator=(const vector& __x);
@@ -577,7 +577,7 @@ public:
#endif
_LIBCPP_INLINE_VISIBILITY
- vector(vector&& __x, const allocator_type& __a);
+ vector(vector&& __x, const __identity_t<allocator_type>& __a);
_LIBCPP_INLINE_VISIBILITY
vector& operator=(vector&& __x)
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
@@ -1261,7 +1261,7 @@ vector<_Tp, _Allocator>::vector(const vector& __x)
}
template <class _Tp, class _Allocator>
-vector<_Tp, _Allocator>::vector(const vector& __x, const allocator_type& __a)
+vector<_Tp, _Allocator>::vector(const vector& __x, const __identity_t<allocator_type>& __a)
: __base(__a)
{
#if _LIBCPP_DEBUG_LEVEL == 2
@@ -1299,7 +1299,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x)
template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
-vector<_Tp, _Allocator>::vector(vector&& __x, const allocator_type& __a)
+vector<_Tp, _Allocator>::vector(vector&& __x, const __identity_t<allocator_type>& __a)
: __base(__a)
{
#if _LIBCPP_DEBUG_LEVEL == 2
@@ -2261,7 +2261,7 @@ public:
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
#endif
- vector(vector&& __v, const allocator_type& __a);
+ vector(vector&& __v, const __identity_t<allocator_type>& __a);
_LIBCPP_INLINE_VISIBILITY
vector& operator=(vector&& __v)
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
@@ -2887,7 +2887,7 @@ inline _LIBCPP_INLINE_VISIBILITY vector<bool, _Allocator>::vector(vector&& __v)
}
template <class _Allocator>
-vector<bool, _Allocator>::vector(vector&& __v, const allocator_type& __a)
+vector<bool, _Allocator>::vector(vector&& __v, const __identity_t<allocator_type>& __a)
: __begin_(nullptr),
__size_(0),
__cap_alloc_(0, __a)
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
index 3023a0bf401e6..139714bc47c33 100644
--- a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp
@@ -133,5 +133,24 @@ int main(int, char**)
assert(m.get_allocator().get_id() == 45);
}
+ {
+ // Examples from LWG3025
+ std::map m{std::pair{1, 1}, {2, 2}, {3, 3}};
+ ASSERT_SAME_TYPE(decltype(m), std::map<int, int>);
+
+ std::map m2{m.begin(), m.end()};
+ ASSERT_SAME_TYPE(decltype(m2), std::map<int, int>);
+ }
+
+ {
+ // Examples from LWG3531
+ std::map m1{{std::pair{1, 2}, {3, 4}}, std::less<int>()};
+ ASSERT_SAME_TYPE(decltype(m1), std::map<int, int>);
+
+ using value_type = std::pair<const int, int>;
+ std::map m2{{value_type{1, 2}, {3, 4}}, std::less<int>()};
+ ASSERT_SAME_TYPE(decltype(m2), std::map<int, int>);
+ }
+
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
index 35be4b4cd2b88..e5b42ebb19cce 100644
--- a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp
@@ -133,5 +133,24 @@ int main(int, char**)
assert(m.get_allocator().get_id() == 45);
}
+ {
+ // Examples from LWG3025
+ std::multimap m{std::pair{1, 1}, {2, 2}, {3, 3}};
+ ASSERT_SAME_TYPE(decltype(m), std::multimap<int, int>);
+
+ std::multimap m2{m.begin(), m.end()};
+ ASSERT_SAME_TYPE(decltype(m2), std::multimap<int, int>);
+ }
+
+ {
+ // Examples from LWG3531
+ std::multimap m1{{std::pair{1, 2}, {3, 4}}, std::less<int>()};
+ ASSERT_SAME_TYPE(decltype(m1), std::multimap<int, int>);
+
+ using value_type = std::pair<const int, int>;
+ std::multimap m2{{value_type{1, 2}, {3, 4}}, std::less<int>()};
+ ASSERT_SAME_TYPE(decltype(m2), std::multimap<int, int>);
+ }
+
return 0;
}
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
index c4f5375bad45a..af155f5f9cbda 100644
--- a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp
@@ -104,21 +104,76 @@ int main(int, char**)
}
{
-// This one is odd - you can pass an allocator in to use, but the allocator
-// has to match the type of the one used by the underlying container
- typedef long double T;
- typedef std::greater<T> Comp;
- typedef test_allocator<T> Alloc;
- typedef std::deque<T, Alloc> Cont;
-
- Cont c{2,3,0,1};
- std::priority_queue<T, Cont, Comp> source(Comp(), c);
- std::priority_queue pri(source, Alloc(2)); // queue(queue &, allocator)
- static_assert(std::is_same_v<decltype(pri)::value_type, T>, "");
- static_assert(std::is_same_v<decltype(pri)::container_type, Cont>, "");
- assert(pri.size() == 4);
- assert(pri.top() == 0);
+ typedef short T;
+ typedef std::greater<T> Comp;
+ typedef test_allocator<T> Alloc;
+ typedef std::deque<T, Alloc> Cont;
+ typedef test_allocator<int> ConvertibleToAlloc;
+ static_assert(std::uses_allocator_v<Cont, ConvertibleToAlloc> &&
+ !std::is_same_v<typename Cont::allocator_type, ConvertibleToAlloc>);
+
+ {
+ Comp comp;
+ Cont cont;
+ std::priority_queue pri(comp, cont, Alloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
+
+ {
+ Comp comp;
+ Cont cont;
+ std::priority_queue pri(comp, cont, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
+
+ {
+ Comp comp;
+ Cont cont;
+ std::priority_queue pri(comp, std::move(cont), Alloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
+
+ {
+ Comp comp;
+ Cont cont;
+ std::priority_queue pri(comp, std::move(cont), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
+ }
+
+ {
+ typedef short T;
+ typedef std::greater<T> Comp;
+ typedef test_allocator<T> Alloc;
+ typedef std::deque<T, Alloc> Cont;
+ typedef test_allocator<int> ConvertibleToAlloc;
+ static_assert(std::uses_allocator_v<Cont, ConvertibleToAlloc> &&
+ !std::is_same_v<typename Cont::allocator_type, ConvertibleToAlloc>);
+
+ {
+ std::priority_queue<T, Cont, Comp> source;
+ std::priority_queue pri(source, Alloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
+
+ {
+ std::priority_queue<T, Cont, Comp> source;
+ std::priority_queue pri(source, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
+
+ {
+ std::priority_queue<T, Cont, Comp> source;
+ std::priority_queue pri(std::move(source), Alloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
+
+ {
+ std::priority_queue<T, Cont, Comp> source;
+ std::priority_queue pri(std::move(source), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+ }
}
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
index 738a3a1701638..4404cc19ba02d 100644
--- a/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/queue/queue.cons/deduct.pass.cpp
@@ -72,21 +72,70 @@ int main(int, char**)
}
{
-// This one is odd - you can pass an allocator in to use, but the allocator
-// has to match the type of the one used by the underlying container
- typedef short T;
- typedef test_allocator<T> Alloc;
- typedef std::deque<T, Alloc> Container;
-
- Container c{0,1,2,3};
- std::queue<T, Container> source(c);
- std::queue que(source, Alloc(2)); // queue(queue &, allocator)
- static_assert(std::is_same_v<decltype(que)::value_type, T>, "");
- static_assert(std::is_same_v<decltype(que)::container_type, Container>, "");
- assert(que.size() == 4);
- assert(que.back() == 3);
+ typedef short T;
+ typedef test_allocator<T> Alloc;
+ typedef std::list<T, Alloc> Cont;
+ typedef test_allocator<int> ConvertibleToAlloc;
+ static_assert(std::uses_allocator_v<Cont, ConvertibleToAlloc> &&
+ !std::is_same_v<typename Cont::allocator_type, ConvertibleToAlloc>);
+
+ {
+ Cont cont;
+ std::queue que(cont, Alloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
+
+ {
+ Cont cont;
+ std::queue que(cont, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
+
+ {
+ Cont cont;
+ std::queue que(std::move(cont), Alloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
+
+ {
+ Cont cont;
+ std::queue que(std::move(cont), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
}
+ {
+ typedef short T;
+ typedef test_allocator<T> Alloc;
+ typedef std::list<T, Alloc> Cont;
+ typedef test_allocator<int> ConvertibleToAlloc;
+ static_assert(std::uses_allocator_v<Cont, ConvertibleToAlloc> &&
+ !std::is_same_v<typename Cont::allocator_type, ConvertibleToAlloc>);
+
+ {
+ std::queue<T, Cont> source;
+ std::queue que(source, Alloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
+
+ {
+ std::queue<T, Cont> source;
+ std::queue que(source, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
+
+ {
+ std::queue<T, Cont> source;
+ std::queue que(std::move(source), Alloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
+
+ {
+ std::queue<T, Cont> source;
+ std::queue que(std::move(source), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(que), std::queue<T, Cont>>);
+ }
+ }
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
index fb211f6570d77..5e279fcedbdd6 100644
--- a/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/stack/stack.cons/deduct.pass.cpp
@@ -22,6 +22,7 @@
#include <stack>
+#include <deque>
#include <vector>
#include <list>
#include <iterator>
@@ -75,21 +76,70 @@ int main(int, char**)
}
{
-// This one is odd - you can pass an allocator in to use, but the allocator
-// has to match the type of the one used by the underlying container
- typedef short T;
- typedef test_allocator<T> Alloc;
- typedef std::deque<T, Alloc> Container;
-
- Container c{0,1,2,3};
- std::stack<T, Container> source(c);
- std::stack stk(source, Alloc(2)); // stack(stack &, allocator)
- static_assert(std::is_same_v<decltype(stk)::value_type, T>, "");
- static_assert(std::is_same_v<decltype(stk)::container_type, Container>, "");
- assert(stk.size() == 4);
- assert(stk.top() == 3);
+ typedef short T;
+ typedef test_allocator<T> Alloc;
+ typedef std::list<T, Alloc> Cont;
+ typedef test_allocator<int> ConvertibleToAlloc;
+ static_assert(std::uses_allocator_v<Cont, ConvertibleToAlloc> &&
+ !std::is_same_v<typename Cont::allocator_type, ConvertibleToAlloc>);
+
+ {
+ Cont cont;
+ std::stack stk(cont, Alloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
+
+ {
+ Cont cont;
+ std::stack stk(cont, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
+
+ {
+ Cont cont;
+ std::stack stk(std::move(cont), Alloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
+
+ {
+ Cont cont;
+ std::stack stk(std::move(cont), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
}
+ {
+ typedef short T;
+ typedef test_allocator<T> Alloc;
+ typedef std::list<T, Alloc> Cont;
+ typedef test_allocator<int> ConvertibleToAlloc;
+ static_assert(std::uses_allocator_v<Cont, ConvertibleToAlloc> &&
+ !std::is_same_v<typename Cont::allocator_type, ConvertibleToAlloc>);
+
+ {
+ std::stack<T, Cont> source;
+ std::stack stk(source, Alloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
+
+ {
+ std::stack<T, Cont> source;
+ std::stack stk(source, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
+
+ {
+ std::stack<T, Cont> source;
+ std::stack stk(std::move(source), Alloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
+
+ {
+ std::stack<T, Cont> source;
+ std::stack stk(std::move(source), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(stk), std::stack<T, Cont>>);
+ }
+ }
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
index 1a143819106e7..3f0e16f4d1674 100644
--- a/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// <array>
+// <deque>
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: libcpp-no-deduction-guides
@@ -95,5 +95,34 @@ int main(int, char**)
assert(deq.size() == 0);
}
- return 0;
+ {
+ typedef test_allocator<short> Alloc;
+ typedef test_allocator<int> ConvertibleToAlloc;
+
+ {
+ std::deque<short, Alloc> source;
+ std::deque deq(source, Alloc(2));
+ static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+ }
+
+ {
+ std::deque<short, Alloc> source;
+ std::deque deq(source, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+ }
+
+ {
+ std::deque<short, Alloc> source;
+ std::deque deq(std::move(source), Alloc(2));
+ static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+ }
+
+ {
+ std::deque<short, Alloc> source;
+ std::deque deq(std::move(source), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(deq), decltype(source)>);
+ }
+ }
+
+ return 0;
}
diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
index 49b1663da6ed4..6c134d840a238 100644
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp
@@ -12,8 +12,8 @@
// template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
-// deque(InputIterator, InputIterator, Allocator = Allocator())
-// -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
+// forward_list(InputIterator, InputIterator, Allocator = Allocator())
+// -> forward_list<typename iterator_traits<InputIterator>::value_type, Allocator>;
//
@@ -100,5 +100,34 @@ int main(int, char**)
assert(std::distance(fwl.begin(), fwl.end()) == 0); // no size for forward_list
}
- return 0;
+ {
+ typedef test_allocator<short> Alloc;
+ typedef test_allocator<int> ConvertibleToAlloc;
+
+ {
+ std::forward_list<short, Alloc> source;
+ std::forward_list fwl(source, Alloc(2));
+ static_assert(std::is_same_v<decltype(fwl), decltype(source)>);
+ }
+
+ {
+ std::forward_list<short, Alloc> source;
+ std::forward_list fwl(source, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(fwl), decltype(source)>);
+ }
+
+ {
+ std::forward_list<short, Alloc> source;
+ std::forward_list fwl(std::move(source), Alloc(2));
+ static_assert(std::is_same_v<decltype(fwl), decltype(source)>);
+ }
+
+ {
+ std::forward_list<short, Alloc> source;
+ std::forward_list fwl(std::move(source), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(fwl), decltype(source)>);
+ }
+ }
+
+ return 0;
}
diff --git a/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
index 766288940b911..9196317e81053 100644
--- a/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/list/list.cons/deduct.pass.cpp
@@ -100,5 +100,34 @@ int main(int, char**)
assert(lst.size() == 0);
}
- return 0;
+ {
+ typedef test_allocator<short> Alloc;
+ typedef test_allocator<int> ConvertibleToAlloc;
+
+ {
+ std::list<short, Alloc> source;
+ std::list lst(source, Alloc(2));
+ static_assert(std::is_same_v<decltype(lst), decltype(source)>);
+ }
+
+ {
+ std::list<short, Alloc> source;
+ std::list lst(source, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(lst), decltype(source)>);
+ }
+
+ {
+ std::list<short, Alloc> source;
+ std::list lst(std::move(source), Alloc(2));
+ static_assert(std::is_same_v<decltype(lst), decltype(source)>);
+ }
+
+ {
+ std::list<short, Alloc> source;
+ std::list lst(std::move(source), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(lst), decltype(source)>);
+ }
+ }
+
+ return 0;
}
diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
index 4921ecda046b0..f343ba84fcaf4 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.pass.cpp
@@ -12,8 +12,8 @@
// template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
-// deque(InputIterator, InputIterator, Allocator = Allocator())
-// -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
+// vector(InputIterator, InputIterator, Allocator = Allocator())
+// -> vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
//
@@ -113,5 +113,34 @@ int main(int, char**)
assert(vec.size() == 0);
}
- return 0;
+ {
+ typedef test_allocator<short> Alloc;
+ typedef test_allocator<int> ConvertibleToAlloc;
+
+ {
+ std::vector<short, Alloc> source;
+ std::vector vec(source, Alloc(2));
+ static_assert(std::is_same_v<decltype(vec), decltype(source)>);
+ }
+
+ {
+ std::vector<short, Alloc> source;
+ std::vector vec(source, ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(vec), decltype(source)>);
+ }
+
+ {
+ std::vector<short, Alloc> source;
+ std::vector vec(std::move(source), Alloc(2));
+ static_assert(std::is_same_v<decltype(vec), decltype(source)>);
+ }
+
+ {
+ std::vector<short, Alloc> source;
+ std::vector vec(std::move(source), ConvertibleToAlloc(2));
+ static_assert(std::is_same_v<decltype(vec), decltype(source)>);
+ }
+ }
+
+ return 0;
}
diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
index 40d0df0630622..195495b5e06b4 100644
--- a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp
@@ -200,5 +200,24 @@ int main(int, char**)
assert(m.get_allocator().get_id() == 48);
}
+ {
+ // Examples from LWG3025
+ std::unordered_map m{std::pair{1, 1}, {2, 2}, {3, 3}};
+ ASSERT_SAME_TYPE(decltype(m), std::unordered_map<int, int>);
+
+ std::unordered_map m2{m.begin(), m.end()};
+ ASSERT_SAME_TYPE(decltype(m2), std::unordered_map<int, int>);
+ }
+
+ {
+ // Examples from LWG3531
+ std::unordered_map m1{{std::pair{1, 2}, {3, 4}}, 0};
+ ASSERT_SAME_TYPE(decltype(m1), std::unordered_map<int, int>);
+
+ using value_type = std::pair<const int, int>;
+ std::unordered_map m2{{value_type{1, 2}, {3, 4}}, 0};
+ ASSERT_SAME_TYPE(decltype(m2), std::unordered_map<int, int>);
+ }
+
return 0;
}
diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
index 995920e904572..a7639ff5b7048 100644
--- a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp
@@ -200,5 +200,24 @@ int main(int, char**)
assert(m.get_allocator().get_id() == 48);
}
+ {
+ // Examples from LWG3025
+ std::unordered_multimap m{std::pair{1, 1}, {2, 2}, {3, 3}};
+ ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, int>);
+
+ std::unordered_multimap m2{m.begin(), m.end()};
+ ASSERT_SAME_TYPE(decltype(m2), std::unordered_multimap<int, int>);
+ }
+
+ {
+ // Examples from LWG3531
+ std::unordered_multimap m1{{std::pair{1, 2}, {3, 4}}, 0};
+ ASSERT_SAME_TYPE(decltype(m1), std::unordered_multimap<int, int>);
+
+ using value_type = std::pair<const int, int>;
+ std::unordered_multimap m2{{value_type{1, 2}, {3, 4}}, 0};
+ ASSERT_SAME_TYPE(decltype(m2), std::unordered_multimap<int, int>);
+ }
+
return 0;
}
More information about the libcxx-commits
mailing list