[libc++] Implement the resolutions of LWG3506 and LWG3522.
authorArthur O'Dwyer <arthur.j.odwyer@gmail.com>
Tue, 2 Mar 2021 05:23:21 +0000 (00:23 -0500)
committerArthur O'Dwyer <arthur.j.odwyer@gmail.com>
Thu, 29 Jul 2021 01:15:20 +0000 (21:15 -0400)
Implement the changes in all language modes.

LWG3506 "Missing allocator-extended constructors for priority_queue"
makes the following changes:
- New allocator-extended constructors for priority_queue.
- New deduction guides targeting those constructors.

LWG3522: "Missing requirement on InputIterator template parameter
for priority_queue constructors". The iterator parameter should be
constrained to actually be an iterator type. `priority_queue{1,2}`
should be SFINAE-friendly ill-formed.

Also, do a drive-by fix in the allocator-extended move constructor:
there's no need to do a `make_heap` after moving from `__q.c` into
our own `c`, because that container was already heapified when it
was part of `__q`. [priqueue.cons.alloc] actually specifies the
behavior and does *not* mention calling `make_heap`. I think this
was just a copy-paste thinko. It dates back to the initial import
of libc++.

Differential Revision: https://reviews.llvm.org/D106824
Differential Revision: https://reviews.llvm.org/D106827

libcxx/docs/Status/Cxx2bIssues.csv
libcxx/docs/Status/RangesIssues.csv
libcxx/include/queue
libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_alloc.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_alloc.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_cont_alloc.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_rcont_alloc.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_iter_constraint.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/deduct.pass.cpp

index 3e745c5..3ed6ff8 100644 (file)
 `3430 <https://wg21.link/LWG3430>`__,"``std::fstream`` & co. should be constructible from string_view","June 2021","",""
 `3462 <https://wg21.link/LWG3462>`__,"ยง[formatter.requirements]: Formatter requirements forbid use of ``fc.arg()``","June 2021","",""
 `3481 <https://wg21.link/LWG3481>`__,"``viewable_range`` mishandles lvalue move-only views","June 2021","",""
-`3506 <https://wg21.link/LWG3506>`__,"Missing allocator-extended constructors for ``priority_queue``","June 2021","",""
+`3506 <https://wg21.link/LWG3506>`__,"Missing allocator-extended constructors for ``priority_queue``","June 2021","|Complete|","14.0"
 `3517 <https://wg21.link/LWG3517>`__,"``join_view::iterator``'s ``iter_swap`` is underconstrained","June 2021","",""
 `3518 <https://wg21.link/LWG3518>`__,"Exception requirements on char trait operations unclear","June 2021","",""
 `3519 <https://wg21.link/LWG3519>`__,"Incomplete synopses for <random> classes","June 2021","",""
 `3520 <https://wg21.link/LWG3520>`__,"``iter_move`` and ``iter_swap`` are inconsistent for ``transform_view::iterator``","June 2021","",""
 `3521 <https://wg21.link/LWG3521>`__,"Overly strict requirements on ``qsort`` and ``bsearch``","June 2021","",""
-`3522 <https://wg21.link/LWG3522>`__,"Missing requirement on ``InputIterator`` template parameter for ``priority_queue`` constructors","June 2021","",""
+`3522 <https://wg21.link/LWG3522>`__,"Missing requirement on ``InputIterator`` template parameter for ``priority_queue`` constructors","June 2021","|Complete|","14.0"
 `3523 <https://wg21.link/LWG3523>`__,"``iota_view::sentinel`` is not always ``iota_view``'s sentinel","June 2021","",""
 `3526 <https://wg21.link/LWG3526>`__,"Return types of ``uses_allocator_construction_args`` unspecified","June 2021","",""
 `3527 <https://wg21.link/LWG3527>`__,"``uses_allocator_construction_args`` handles rvalue pairs of rvalue references incorrectly","June 2021","",""
index 4cd6c3d..5fb2d0d 100644 (file)
@@ -1,4 +1,4 @@
-"Number","Name","Status","Assignee"
+"Number","Name","Status","First released version"
 `P0896R4 <https://wg21.link/P0896R4>`__,<ranges>,,
 `P1035R7 <https://wg21.link/P1035R7>`__,Input Range Adaptors,,
 `P1207R4 <https://wg21.link/P1207R4>`__,Movability Of Single-Pass Iterators,,
@@ -67,7 +67,7 @@
 `LWG3505 <https://wg21.link/lwg3505>`__, split_view::outer-iterator::operator++ misspecified,,
 `LWG3517 <https://wg21.link/LWG3517>`__,"join_view::iterator's iter_swap is underconstrained",,
 `LWG3520 <https://wg21.link/LWG3520>`__,"iter_move and iter_swap are inconsistent for transform_view::iterator",,
-`LWG3522 <https://wg21.link/LWG3522>`__,"Missing requirement on InputIterator template parameter for priority_queue constructors",,
+`LWG3522 <https://wg21.link/LWG3522>`__,"Missing requirement on InputIterator template parameter for priority_queue constructors","|Complete|","14.0"
 `LWG3523 <https://wg21.link/LWG3523>`__,"iota_view::sentinel is not always iota_view's sentinel",,
 `LWG3532 <https://wg21.link/LWG3532>`__,"split_view<V, P>::inner-iterator<true>::operator++(int) should depend on Base",,
 `LWG3533 <https://wg21.link/LWG3533>`__,"Make base() const & consistent across iterator wrappers that supports input_iterators",,
index 42470e3..276fff9 100644 (file)
@@ -115,27 +115,39 @@ public:
     priority_queue() : priority_queue(Compare()) {} // C++20
     explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {}
     priority_queue(const Compare& x, const Container&);
-    explicit priority_queue(const Compare& x = Compare(), Container&&= Container()); // before C++20
+    explicit priority_queue(const Compare& x = Compare(), Container&& = Container()); // before C++20
     priority_queue(const Compare& x, Container&&); // C++20
     template <class InputIterator>
         priority_queue(InputIterator first, InputIterator last,
                        const Compare& comp = Compare());
     template <class InputIterator>
         priority_queue(InputIterator first, InputIterator last,
-                       const Compare& comp, const container_type& c);
+                       const Compare& comp, const Container& c);
     template <class InputIterator>
         priority_queue(InputIterator first, InputIterator last,
-                       const Compare& comp, container_type&& c);
+                       const Compare& comp, Container&& c);
     template <class Alloc>
         explicit priority_queue(const Alloc& a);
     template <class Alloc>
         priority_queue(const Compare& comp, const Alloc& a);
     template <class Alloc>
-        priority_queue(const Compare& comp, const container_type& c,
+        priority_queue(const Compare& comp, const Container& c,
                        const Alloc& a);
     template <class Alloc>
-        priority_queue(const Compare& comp, container_type&& c,
+        priority_queue(const Compare& comp, Container&& c,
                        const Alloc& a);
+    template <class InputIterator>
+        priority_queue(InputIterator first, InputIterator last,
+                       const Alloc& a);
+    template <class InputIterator>
+        priority_queue(InputIterator first, InputIterator last,
+                       const Compare& comp, const Alloc& a);
+    template <class InputIterator>
+        priority_queue(InputIterator first, InputIterator last,
+                       const Compare& comp, const Container& c, const Alloc& a);
+    template <class InputIterator>
+        priority_queue(InputIterator first, InputIterator last,
+                       const Compare& comp, Container&& c, const Alloc& a);
     template <class Alloc>
         priority_queue(const priority_queue& q, const Alloc& a);
     template <class Alloc>
@@ -160,15 +172,30 @@ priority_queue(Compare, Container)
     -> priority_queue<typename Container::value_type, Container, Compare>; // C++17
 
 template<class InputIterator,
-         class Compare = less<typename iterator_traits<InputIterator>::value_type>,
-         class Container = vector<typename iterator_traits<InputIterator>::value_type>>
+         class Compare = less<iter-value-type<InputIterator>>,
+         class Container = vector<iter-value-type<InputIterator>>>
 priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container())
-    -> priority_queue<typename iterator_traits<InputIterator>::value_type, Container, Compare>; // C++17
+    -> priority_queue<iter-value-type<InputIterator>, Container, Compare>; // C++17
 
 template<class Compare, class Container, class Allocator>
 priority_queue(Compare, Container, Allocator)
     -> priority_queue<typename Container::value_type, Container, Compare>; // C++17
 
+template<class InputIterator, class Allocator>
+priority_queue(InputIterator, InputIterator, Allocator)
+    -> priority_queue<iter-value-type<InputIterator>,
+                      vector<iter-value-type<InputIterator>, Allocator>,
+                      less<iter-value-type<InputIterator>>>;
+
+template<class InputIterator, class Compare, class Allocator>
+priority_queue(InputIterator, InputIterator, Compare, Allocator)
+    -> priority_queue<iter-value-type<InputIterator>,
+                      vector<iter-value-type<InputIterator>, Allocator>, Compare>;
+
+template<class InputIterator, class Compare, class Container, class Allocator>
+priority_queue(InputIterator, InputIterator, Compare, Container, Allocator)
+    -> priority_queue<typename Container::value_type, Container, Compare>;
+
 template <class T, class Container, class Compare>
   void swap(priority_queue<T, Container, Compare>& x,
             priority_queue<T, Container, Compare>& y)
@@ -464,16 +491,16 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     priority_queue(const value_compare& __comp, container_type&& __c);
 #endif
-    template <class _InputIter>
+    template <class _InputIter, class = _EnableIf<__is_cpp17_input_iterator<_InputIter>::value> >
         _LIBCPP_INLINE_VISIBILITY
         priority_queue(_InputIter __f, _InputIter __l,
                        const value_compare& __comp = value_compare());
-    template <class _InputIter>
+    template <class _InputIter, class = _EnableIf<__is_cpp17_input_iterator<_InputIter>::value> >
         _LIBCPP_INLINE_VISIBILITY
         priority_queue(_InputIter __f, _InputIter __l,
                        const value_compare& __comp, const container_type& __c);
 #ifndef _LIBCPP_CXX03_LANG
-    template <class _InputIter>
+    template <class _InputIter, class = _EnableIf<__is_cpp17_input_iterator<_InputIter>::value> >
         _LIBCPP_INLINE_VISIBILITY
         priority_queue(_InputIter __f, _InputIter __l,
                        const value_compare& __comp, container_type&& __c);
@@ -507,6 +534,31 @@ public:
                        _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0);
 #endif // _LIBCPP_CXX03_LANG
 
+    template <class _InputIter, class _Alloc, class = _EnableIf<__is_cpp17_input_iterator<_InputIter>::value> >
+        _LIBCPP_INLINE_VISIBILITY
+        priority_queue(_InputIter __f, _InputIter __l, const _Alloc& __a,
+                       _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0);
+
+    template <class _InputIter, class _Alloc, class = _EnableIf<__is_cpp17_input_iterator<_InputIter>::value> >
+        _LIBCPP_INLINE_VISIBILITY
+        priority_queue(_InputIter __f, _InputIter __l,
+                       const value_compare& __comp, const _Alloc& __a,
+                       _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0);
+
+    template <class _InputIter, class _Alloc, class = _EnableIf<__is_cpp17_input_iterator<_InputIter>::value> >
+        _LIBCPP_INLINE_VISIBILITY
+        priority_queue(_InputIter __f, _InputIter __l,
+                       const value_compare& __comp, const container_type& __c, const _Alloc& __a,
+                       _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0);
+
+#ifndef _LIBCPP_CXX03_LANG
+    template <class _InputIter, class _Alloc, class = _EnableIf<__is_cpp17_input_iterator<_InputIter>::value> >
+        _LIBCPP_INLINE_VISIBILITY
+        priority_queue(_InputIter __f, _InputIter __l,
+                       const value_compare& __comp, container_type&& __c, const _Alloc& __a,
+                       _EnableIf<uses_allocator<container_type, _Alloc>::value>* = 0);
+#endif  // _LIBCPP_CXX03_LANG
+
     _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
     bool            empty() const {return c.empty();}
     _LIBCPP_INLINE_VISIBILITY
@@ -560,6 +612,33 @@ template<class _Compare,
 >
 priority_queue(_Compare, _Container, _Alloc)
     -> priority_queue<typename _Container::value_type, _Container, _Compare>;
+
+template<class _InputIterator, class _Allocator,
+         class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value>,
+         class = _EnableIf<__is_allocator<_Allocator>::value>
+>
+priority_queue(_InputIterator, _InputIterator, _Allocator)
+    -> priority_queue<__iter_value_type<_InputIterator>,
+                      vector<__iter_value_type<_InputIterator>, _Allocator>,
+                      less<__iter_value_type<_InputIterator>>>;
+
+template<class _InputIterator, class _Compare, class _Allocator,
+         class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value>,
+         class = _EnableIf<!__is_allocator<_Compare>::value>,
+         class = _EnableIf<__is_allocator<_Allocator>::value>
+>
+priority_queue(_InputIterator, _InputIterator, _Compare, _Allocator)
+    -> priority_queue<__iter_value_type<_InputIterator>,
+                      vector<__iter_value_type<_InputIterator>, _Allocator>, _Compare>;
+
+template<class _InputIterator, class _Compare, class _Container, class _Alloc,
+         class = _EnableIf<__is_cpp17_input_iterator<_InputIterator>::value>,
+         class = _EnableIf<!__is_allocator<_Compare>::value>,
+         class = _EnableIf<!__is_allocator<_Container>::value>,
+         class = _EnableIf<uses_allocator<_Container, _Alloc>::value>
+>
+priority_queue(_InputIterator, _InputIterator, _Compare, _Container, _Alloc)
+    -> priority_queue<typename _Container::value_type, _Container, _Compare>;
 #endif
 
 template <class _Tp, class _Container, class _Compare>
@@ -587,7 +666,7 @@ priority_queue<_Tp, _Container, _Compare>::priority_queue(const value_compare& _
 #endif // _LIBCPP_CXX03_LANG
 
 template <class _Tp, class _Container, class _Compare>
-template <class _InputIter>
+template <class _InputIter, class>
 inline
 priority_queue<_Tp, _Container, _Compare>::priority_queue(_InputIter __f, _InputIter __l,
                                                           const value_compare& __comp)
@@ -598,7 +677,7 @@ priority_queue<_Tp, _Container, _Compare>::priority_queue(_InputIter __f, _Input
 }
 
 template <class _Tp, class _Container, class _Compare>
-template <class _InputIter>
+template <class _InputIter, class>
 inline
 priority_queue<_Tp, _Container, _Compare>::priority_queue(_InputIter __f, _InputIter __l,
                                                           const value_compare& __comp,
@@ -613,7 +692,7 @@ priority_queue<_Tp, _Container, _Compare>::priority_queue(_InputIter __f, _Input
 #ifndef _LIBCPP_CXX03_LANG
 
 template <class _Tp, class _Container, class _Compare>
-template <class _InputIter>
+template <class _InputIter, class>
 inline
 priority_queue<_Tp, _Container, _Compare>::priority_queue(_InputIter __f, _InputIter __l,
                                                           const value_compare& __comp,
@@ -669,7 +748,6 @@ priority_queue<_Tp, _Container, _Compare>::priority_queue(const priority_queue&
     : c(__q.c, __a),
       comp(__q.comp)
 {
-    _VSTD::make_heap(c.begin(), c.end(), comp);
 }
 
 #ifndef _LIBCPP_CXX03_LANG
@@ -696,10 +774,64 @@ priority_queue<_Tp, _Container, _Compare>::priority_queue(priority_queue&& __q,
     : c(_VSTD::move(__q.c), __a),
       comp(_VSTD::move(__q.comp))
 {
+}
+
+#endif  // _LIBCPP_CXX03_LANG
+
+template <class _Tp, class _Container, class _Compare>
+template <class _InputIter, class _Alloc, class>
+inline
+priority_queue<_Tp, _Container, _Compare>::priority_queue(
+        _InputIter __f, _InputIter __l, const _Alloc& __a,
+        _EnableIf<uses_allocator<container_type, _Alloc>::value>*)
+    : c(__f, __l, __a),
+      comp()
+{
     _VSTD::make_heap(c.begin(), c.end(), comp);
 }
 
-#endif // _LIBCPP_CXX03_LANG
+template <class _Tp, class _Container, class _Compare>
+template <class _InputIter, class _Alloc, class>
+inline
+priority_queue<_Tp, _Container, _Compare>::priority_queue(
+        _InputIter __f, _InputIter __l,
+        const value_compare& __comp, const _Alloc& __a,
+        _EnableIf<uses_allocator<container_type, _Alloc>::value>*)
+    : c(__f, __l, __a),
+      comp(__comp)
+{
+    _VSTD::make_heap(c.begin(), c.end(), comp);
+}
+
+template <class _Tp, class _Container, class _Compare>
+template <class _InputIter, class _Alloc, class>
+inline
+priority_queue<_Tp, _Container, _Compare>::priority_queue(
+        _InputIter __f, _InputIter __l,
+        const value_compare& __comp, const container_type& __c, const _Alloc& __a,
+        _EnableIf<uses_allocator<container_type, _Alloc>::value>*)
+    : c(__c, __a),
+      comp(__comp)
+{
+    c.insert(c.end(), __f, __l);
+    _VSTD::make_heap(c.begin(), c.end(), comp);
+}
+
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Tp, class _Container, class _Compare>
+template <class _InputIter, class _Alloc, class>
+inline
+priority_queue<_Tp, _Container, _Compare>::priority_queue(
+        _InputIter __f, _InputIter __l, const value_compare& __comp,
+        container_type&& __c, const _Alloc& __a,
+        _EnableIf<uses_allocator<container_type, _Alloc>::value>*)
+    : c(_VSTD::move(__c), __a),
+      comp(__comp)
+{
+    c.insert(c.end(), __f, __l);
+    _VSTD::make_heap(c.begin(), c.end(), comp);
+}
+#endif  // _LIBCPP_CXX03_LANG
 
 template <class _Tp, class _Container, class _Compare>
 inline
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_alloc.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_alloc.pass.cpp
new file mode 100644 (file)
index 0000000..e413cb5
--- /dev/null
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <queue>
+
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Alloc& a);
+
+#include <queue>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+
+template<class T, class Cont, class Comp = std::less<T> >
+struct PQ : std::priority_queue<T, Cont, Comp> {
+    typedef std::priority_queue<T, Cont, Comp> base;
+
+    template<class It, class Alloc>
+    explicit PQ(It first, It last, const Alloc& a) : base(first, last, a) {}
+
+    using base::c;
+};
+
+int main(int, char**)
+{
+    int a[] = {3, 5, 2, 0, 6, 8, 1};
+    typedef test_allocator<int> Alloc;
+    PQ<int, std::vector<int, Alloc> > q(a, a+7, Alloc(2));
+    assert(q.size() == 7);
+    assert(q.top() == 8);
+    assert(q.c.get_allocator() == Alloc(2));
+
+    return 0;
+}
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_alloc.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_alloc.pass.cpp
new file mode 100644 (file)
index 0000000..5bea931
--- /dev/null
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <queue>
+
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Compare& comp, const Alloc& a);
+
+#include <queue>
+#include <cassert>
+#include <functional>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+
+template<class T, class Cont, class Comp = std::less<T> >
+struct PQ : std::priority_queue<T, Cont, Comp> {
+    typedef std::priority_queue<T, Cont, Comp> base;
+
+    template<class It, class Alloc>
+    explicit PQ(It first, It last, const Comp& compare, const Alloc& a) : base(first, last, compare, a) {}
+
+    using base::c;
+};
+
+int main(int, char**)
+{
+    int a[] = {3, 5, 2, 0, 6, 8, 1};
+    typedef test_allocator<int> Alloc;
+    PQ<int, std::vector<int, Alloc>, std::greater<int> > q(a, a+7, std::greater<int>(), Alloc(2));
+    assert(q.size() == 7);
+    assert(q.top() == 0);
+    assert(q.c.get_allocator() == Alloc(2));
+
+    return 0;
+}
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_cont_alloc.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_cont_alloc.pass.cpp
new file mode 100644 (file)
index 0000000..1a7288e
--- /dev/null
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <queue>
+
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last,
+//                  const Compare& comp, const Container& c, const Alloc& a);
+
+#include <queue>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+
+template<class T, class Cont, class Comp = std::less<T> >
+struct PQ : std::priority_queue<T, Cont, Comp> {
+    typedef std::priority_queue<T, Cont, Comp> base;
+
+    template<class It, class Alloc>
+    explicit PQ(It first, It last, const Comp& compare, const Cont& v, const Alloc& a) : base(first, last, compare, v, a) {}
+
+    using base::c;
+};
+
+int main(int, char**)
+{
+    typedef test_allocator<int> Alloc;
+    int a[] = {3, 5, 2, 0, 6, 8, 1};
+    std::vector<int, Alloc> v(a, a+3);
+    PQ<int, std::vector<int, Alloc> > q(a+3, a+7, std::less<int>(), v, Alloc(2));
+    assert(q.size() == 7);
+    assert(q.top() == 8);
+    assert(q.c.get_allocator() == Alloc(2));
+
+    return 0;
+}
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_rcont_alloc.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons.alloc/ctor_iter_iter_comp_rcont_alloc.pass.cpp
new file mode 100644 (file)
index 0000000..31595f4
--- /dev/null
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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++03
+
+// <queue>
+
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last,
+//                  const Compare& comp, Container&& c, const Alloc& a);
+
+#include <queue>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "MoveOnly.h"
+
+template<class T, class Cont, class Comp = std::less<T> >
+struct PQ : std::priority_queue<T, Cont, Comp> {
+    typedef std::priority_queue<T, Cont, Comp> base;
+
+    template<class It, class Alloc>
+    explicit PQ(It first, It last, const Comp& compare, Cont&& v, const Alloc& a) : base(first, last, compare, std::move(v), a) {}
+
+    using base::c;
+};
+
+int main(int, char**)
+{
+    using Alloc = test_allocator<MoveOnly>;
+    int a[] = {3, 5, 2, 0, 6, 8, 1};
+    PQ<MoveOnly, std::vector<MoveOnly, Alloc>> q(
+        a+3, a+7, std::less<MoveOnly>(),
+        std::vector<MoveOnly, Alloc>(a, a+3), Alloc(2));
+    assert(q.size() == 7);
+    assert(q.top() == MoveOnly(8));
+    assert(q.c.get_allocator() == Alloc(2));
+
+    return 0;
+}
diff --git a/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_iter_constraint.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/priority.queue/priqueue.cons/ctor_iter_constraint.compile.pass.cpp
new file mode 100644 (file)
index 0000000..283cbc0
--- /dev/null
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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++03
+
+// <queue>
+
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Compare& = Compare());
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Compare&, const Container&);
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Compare&, Container&&);
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Alloc&);
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Compare&, const Alloc&);
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Compare&, const Container&, const Alloc&);
+// template <class InputIterator>
+//   priority_queue(InputIterator first, InputIterator last, const Compare&, Container&&, const Alloc&);
+
+#include <queue>
+#include <type_traits>
+#include <vector>
+
+// Sanity-check that std::vector is constructible from two ints...
+static_assert( std::is_constructible<std::vector<int>,         int*, int*>::value, "");
+static_assert( std::is_constructible<std::vector<int>,         int , int >::value, "");
+
+// ...but std::priority_queue is not.
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int >::value, "");
+
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*, std::less<int>>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int , std::less<int>>::value, "");
+
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*, std::less<int>, std::vector<int>>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int , std::less<int>, std::vector<int>>::value, "");
+
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*, std::less<int>, std::vector<int>&>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int , std::less<int>, std::vector<int>&>::value, "");
+
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*, std::allocator<int>>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int , std::allocator<int>>::value, "");
+
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*, std::less<int>, std::allocator<int>>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int , std::less<int>, std::allocator<int>>::value, "");
+
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*, std::less<int>, std::vector<int>, std::allocator<int>>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int , std::less<int>, std::vector<int>, std::allocator<int>>::value, "");
+
+static_assert( std::is_constructible<std::priority_queue<int>, int*, int*, std::less<int>, std::vector<int>&, std::allocator<int>>::value, "");
+static_assert(!std::is_constructible<std::priority_queue<int>, int , int , std::less<int>, std::vector<int>&, std::allocator<int>>::value, "");
index af155f5..89ff2e7 100644 (file)
@@ -143,6 +143,7 @@ int main(int, char**)
 
     {
         typedef short T;
+        typedef signed char ConvertibleToT;
         typedef std::greater<T> Comp;
         typedef test_allocator<T> Alloc;
         typedef std::deque<T, Alloc> Cont;
@@ -173,6 +174,70 @@ int main(int, char**)
         std::priority_queue pri(std::move(source), ConvertibleToAlloc(2));
         static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, 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>>);
+        }
+
+        {
+        Cont cont;
+        std::priority_queue pri(Comp(), cont, ConvertibleToAlloc(2));
+        static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, 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>>);
+        }
+
+        {
+        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>>);
+        }
+
+        {
+        T a[2] = {};
+        std::priority_queue pri(a, a+2, Alloc(2));
+        static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, std::vector<T, Alloc>>>);
+        }
+
+        {
+        T a[2] = {};
+        std::priority_queue pri(a, a+2, Comp(), Alloc(2));
+        static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, std::vector<T, Alloc>, Comp>>);
+        }
+
+        {
+        Cont cont;
+        ConvertibleToT a[2] = {};
+        std::priority_queue pri(a, a+2, Comp(), cont, Alloc(2));
+        static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+        }
+
+        {
+        Cont cont;
+        ConvertibleToT a[2] = {};
+        std::priority_queue pri(a, a+2, Comp(), cont, ConvertibleToAlloc(2));
+        static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+        }
+
+        {
+        Cont cont;
+        ConvertibleToT a[2] = {};
+        std::priority_queue pri(a, a+2, Comp(), std::move(cont), Alloc(2));
+        static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+        }
+
+        {
+        Cont cont;
+        ConvertibleToT a[2] = {};
+        std::priority_queue pri(a, a+2, Comp(), std::move(cont), ConvertibleToAlloc(2));
+        static_assert(std::is_same_v<decltype(pri), std::priority_queue<T, Cont, Comp>>);
+        }
     }
 
     return 0;