diff --git a/libcxx/include/queue b/libcxx/include/queue --- a/libcxx/include/queue +++ b/libcxx/include/queue @@ -43,6 +43,7 @@ explicit queue(container_type&& c) template queue(InputIterator first, InputIterator last); // since C++23 + template R> queue(from_range_t, R&& rg); // since C++23 template explicit queue(const Alloc& a); template @@ -55,6 +56,8 @@ queue(queue&& q, const Alloc& a); template queue(InputIterator first, InputIterator last, const Alloc&); // since C++23 + template R, class Alloc> + queue(from_range_t, R&& rg, const Alloc&); // since C++23 bool empty() const; size_type size() const; @@ -66,6 +69,8 @@ void push(const value_type& v); void push(value_type&& v); + template R> + void push_range(R&& rg); // C++23 template reference emplace(Args&&... args); // reference in C++17 void pop(); @@ -78,6 +83,9 @@ template queue(InputIterator, InputIterator) -> queue>; // since C++23 +template + queue(from_range_t, R&&) -> queue>; // since C++23 + template queue(Container, Allocator) -> queue; // C++17 @@ -86,6 +94,10 @@ -> queue, deque, Allocator>>; // since C++23 +template + queue(from_range_t, R&&, Allocator) + -> queue, deque, Allocator>>; // since C++23 + template bool operator==(const queue& x,const queue& y); @@ -138,6 +150,8 @@ template priority_queue(InputIterator first, InputIterator last, const Compare& comp, Container&& c); + template R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); // since C++23 template explicit priority_queue(const Alloc& a); template @@ -160,6 +174,10 @@ template priority_queue(InputIterator first, InputIterator last, const Compare& comp, Container&& c, const Alloc& a); + template R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); // since C++23 + template R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc&); // since C++23 template priority_queue(const priority_queue& q, const Alloc& a); template @@ -171,6 +189,8 @@ void push(const value_type& v); void push(value_type&& v); + template R> + void push_range(R&& rg); // C++23 template void emplace(Args&&... args); void pop(); @@ -189,6 +209,10 @@ priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) -> priority_queue, Container, Compare>; // C++17 +template>> + priority_queue(from_range_t, R&&, Compare = Compare()) + -> priority_queue, vector>, Compare>; // C++23 + template priority_queue(Compare, Container, Allocator) -> priority_queue; // C++17 @@ -208,6 +232,15 @@ priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) -> priority_queue; // C++17 +template + priority_queue(from_range_t, R&&, Compare, Allocator) + -> priority_queue, vector, Allocator>, + Compare>; // C++23 + +template + priority_queue(from_range_t, R&&, Allocator) + -> priority_queue, vector, Allocator>>; // C++23 + template void swap(priority_queue& x, priority_queue& y) @@ -220,11 +253,17 @@ #include <__algorithm/make_heap.h> #include <__algorithm/pop_heap.h> #include <__algorithm/push_heap.h> +#include <__algorithm/ranges_copy.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__functional/operations.h> +#include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/uses_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> #include <__utility/forward.h> #include #include @@ -283,12 +322,24 @@ _LIBCPP_HIDE_FROM_ABI queue(_InputIterator __first, _InputIterator __last) : c(__first, __last) {} + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + queue(from_range_t, _Range&& __range) : c(from_range, std::forward<_Range>(__range)) {} + template ::value>, class = __enable_if_t::value>> _LIBCPP_HIDE_FROM_ABI queue(_InputIterator __first, _InputIterator __second, const _Alloc& __alloc) : c(__first, __second, __alloc) {} + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = __enable_if_t::value>> + _LIBCPP_HIDE_FROM_ABI + queue(from_range_t, _Range&& __range, const _Alloc& __alloc) + : c(from_range, std::forward<_Range>(__range), __alloc) {} + #endif _LIBCPP_INLINE_VISIBILITY @@ -360,6 +411,21 @@ #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void push(value_type&& __v) {c.push_back(_VSTD::move(__v));} + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void push_range(_Range&& __range) { + if constexpr (requires (container_type& __c) { + __c.append_range(std::forward<_Range>(__range)); + }) { + c.append_range(std::forward<_Range>(__range)); + } else { + ranges::copy(std::forward<_Range>(__range), std::back_inserter(c)); + } + } +#endif + template _LIBCPP_INLINE_VISIBILITY #if _LIBCPP_STD_VER >= 17 @@ -418,12 +484,22 @@ queue(_InputIterator, _InputIterator) -> queue<__iter_value_type<_InputIterator>>; +template +queue(from_range_t, _Range&&) + -> queue>; + template ::value>, class = __enable_if_t<__is_allocator<_Alloc>::value>> queue(_InputIterator, _InputIterator, _Alloc) -> queue<__iter_value_type<_InputIterator>, deque<__iter_value_type<_InputIterator>, _Alloc>>; + +template ::value>> +queue(from_range_t, _Range&&, _Alloc) + -> queue, deque, _Alloc>>; #endif template @@ -557,6 +633,17 @@ priority_queue(_InputIter __f, _InputIter __l, const value_compare& __comp, container_type&& __c); #endif // _LIBCPP_CXX03_LANG + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + priority_queue(from_range_t, _Range&& __range, const value_compare& __comp = value_compare()) + : c(from_range, std::forward<_Range>(__range)), + comp(__comp) { + std::make_heap(c.begin(), c.end(), comp); + } +#endif + template _LIBCPP_INLINE_VISIBILITY explicit priority_queue(const _Alloc& __a, @@ -611,6 +698,30 @@ __enable_if_t::value>* = 0); #endif // _LIBCPP_CXX03_LANG +#if _LIBCPP_STD_VER >= 23 + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = enable_if_t::value>> + _LIBCPP_HIDE_FROM_ABI + priority_queue(from_range_t, _Range&& __range, const value_compare& __comp, const _Alloc& __a) + : c(from_range, std::forward<_Range>(__range), __a), + comp(__comp) { + std::make_heap(c.begin(), c.end(), comp); + } + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = enable_if_t::value>> + _LIBCPP_HIDE_FROM_ABI + priority_queue(from_range_t, _Range&& __range, const _Alloc& __a) + : c(from_range, std::forward<_Range>(__range), __a), + comp() { + std::make_heap(c.begin(), c.end(), comp); + } + +#endif + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const {return c.empty();} _LIBCPP_INLINE_VISIBILITY @@ -623,6 +734,23 @@ #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void push(value_type&& __v); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void push_range(_Range&& __range) { + if constexpr (requires (container_type& __c) { + __c.append_range(std::forward<_Range>(__range)); + }) { + c.append_range(std::forward<_Range>(__range)); + } else { + ranges::copy(std::forward<_Range>(__range), std::back_inserter(c)); + } + + std::make_heap(c.begin(), c.end(), comp); + } +#endif + template _LIBCPP_INLINE_VISIBILITY void emplace(_Args&&... __args); @@ -695,6 +823,31 @@ -> priority_queue; #endif +#if _LIBCPP_STD_VER >= 23 + +template >, + class = enable_if_t::value>> +priority_queue(from_range_t, _Range&&, _Compare = _Compare()) + -> priority_queue, vector>, _Compare>; + +template ::value>, + class = enable_if_t<__is_allocator<_Alloc>::value>> +priority_queue(from_range_t, _Range&&, _Compare, _Alloc) + -> priority_queue, vector, _Alloc>, + _Compare>; + +template ::value>> +priority_queue(from_range_t, _Range&&, _Alloc) + -> priority_queue, vector, _Alloc>>; + +#endif + template inline priority_queue<_Tp, _Container, _Compare>::priority_queue(const _Compare& __comp, diff --git a/libcxx/include/stack b/libcxx/include/stack --- a/libcxx/include/stack +++ b/libcxx/include/stack @@ -42,6 +42,7 @@ explicit stack(const container_type& c); explicit stack(container_type&& c); template stack(InputIterator first, InputIterator last); // since C++23 + template R> stack(from_range_t, R&& rg); // since C++23 template explicit stack(const Alloc& a); template stack(const container_type& c, const Alloc& a); template stack(container_type&& c, const Alloc& a); @@ -49,6 +50,8 @@ template stack(stack&& c, const Alloc& a); template stack(InputIterator first, InputIterator last, const Alloc&); // since C++23 + template R, class Alloc> + stack(from_range_t, R&& rg, const Alloc&); // since C++23 bool empty() const; size_type size() const; @@ -57,6 +60,8 @@ void push(const value_type& x); void push(value_type&& x); + template R> + void push_range(R&& rg); // C++23 template reference emplace(Args&&... args); // reference in C++17 void pop(); @@ -69,6 +74,9 @@ template stack(InputIterator, InputIterator) -> stack>; // since C++23 +template + stack(from_range_t, R&&) -> stack>; // since C++23 + template stack(Container, Allocator) -> stack; // C++17 @@ -77,6 +85,10 @@ -> stack, deque, Allocator>>; // since C++23 +template + stack(from_range_t, R&&, Allocator) + -> stack, deque, Allocator>>; // since C++23 + template bool operator==(const stack& x, const stack& y); template @@ -98,10 +110,16 @@ */ +#include <__algorithm/ranges_copy.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/uses_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> #include <__type_traits/is_same.h> #include <__utility/forward.h> #include @@ -210,12 +228,24 @@ _LIBCPP_HIDE_FROM_ABI stack(_InputIterator __first, _InputIterator __last) : c(__first, __last) {} + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + stack(from_range_t, _Range&& __range) : c(from_range, std::forward<_Range>(__range)) {} + template ::value>, class = __enable_if_t::value>> _LIBCPP_HIDE_FROM_ABI stack(_InputIterator __first, _InputIterator __last, const _Alloc& __alloc) : c(__first, __last, __alloc) {} + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = __enable_if_t::value>> + _LIBCPP_HIDE_FROM_ABI + stack(from_range_t, _Range&& __range, const _Alloc& __alloc) + : c(from_range, std::forward<_Range>(__range), __alloc) {} + #endif _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY @@ -233,6 +263,20 @@ _LIBCPP_INLINE_VISIBILITY void push(value_type&& __v) {c.push_back(_VSTD::move(__v));} +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void push_range(_Range&& __range) { + if constexpr (requires (container_type& __c) { + __c.append_range(std::forward<_Range>(__range)); + }) { + c.append_range(std::forward<_Range>(__range)); + } else { + ranges::copy(std::forward<_Range>(__range), std::back_inserter(c)); + } + } +#endif + template _LIBCPP_INLINE_VISIBILITY #if _LIBCPP_STD_VER >= 17 @@ -290,12 +334,22 @@ stack(_InputIterator, _InputIterator) -> stack<__iter_value_type<_InputIterator>>; +template +stack(from_range_t, _Range&&) -> stack>; + template::value>, class = __enable_if_t<__is_allocator<_Alloc>::value>> stack(_InputIterator, _InputIterator, _Alloc) -> stack<__iter_value_type<_InputIterator>, deque<__iter_value_type<_InputIterator>, _Alloc>>; + +template ::value>> +stack(from_range_t, _Range&&, _Alloc) + -> stack, deque, _Alloc>>; + #endif template diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -777,6 +777,7 @@ stack deque stack functional stack initializer_list +stack limits stack type_traits stack version stdexcept cstdlib diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -778,6 +778,7 @@ stack deque stack functional stack initializer_list +stack limits stack type_traits stack version stdexcept cstdlib diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -780,6 +780,7 @@ stack deque stack functional stack initializer_list +stack limits stack type_traits stack version stdexcept cstdlib diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -780,6 +780,7 @@ stack deque stack functional stack initializer_list +stack limits stack type_traits stack version stdexcept cstdlib diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -786,6 +786,7 @@ stack deque stack functional stack initializer_list +stack limits stack type_traits stack version stdexcept cstdlib diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -437,6 +437,7 @@ ostream version queue compare queue cstddef +queue cstdint queue deque queue initializer_list queue limits @@ -529,8 +530,10 @@ sstream version stack compare stack cstddef +stack cstdint stack deque stack initializer_list +stack limits stack version stdexcept iosfwd stop_token atomic diff --git a/libcxx/test/std/containers/container.adaptors/from_range_container_adaptors.h b/libcxx/test/std/containers/container.adaptors/from_range_container_adaptors.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/from_range_container_adaptors.h @@ -0,0 +1,229 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_FROM_RANGE_CONTAINER_ADAPTORS_H +#define SUPPORT_FROM_RANGE_CONTAINER_ADAPTORS_H + +#include +#include +#include +#include +#include +#include +#include + +#include "../from_range_helpers.h" +#include "MoveOnly.h" +#include "almost_satisfies_types.h" +#include "count_new.h" +#include "test_macros.h" +#include "unwrap_container_adaptor.h" + +template +concept HasFromRangeCtr = requires (Range&& range) { + Container(std::from_range, std::forward(range)); + Container(std::from_range, std::forward(range), std::allocator()); +}; + +template