diff options
Diffstat (limited to 'libcxx')
90 files changed, 1593 insertions, 558 deletions
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 8fba6db..d5ed918 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -426,6 +426,10 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_algorithms`` ``202306L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_flat_map`` ``202502L`` + ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_flat_set`` ``202502L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_forward_list`` ``202502L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_list`` ``202502L`` @@ -474,7 +478,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_is_virtual_base_of`` ``202406L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_is_within_lifetime`` *unimplemented* + ``__cpp_lib_is_within_lifetime`` ``202306L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_linalg`` *unimplemented* ---------------------------------------------------------- ----------------- diff --git a/libcxx/docs/index.rst b/libcxx/docs/index.rst index 495ccce..03dfb9d 100644 --- a/libcxx/docs/index.rst +++ b/libcxx/docs/index.rst @@ -132,7 +132,7 @@ velocity, libc++ drops support for older compilers as newer ones are released. ============ =================== ========================== ===================== Compiler Versions Restrictions Support policy ============ =================== ========================== ===================== -Clang 19, 20, 21-git latest two stable releases per `LLVM's release page <https://releases.llvm.org>`_ and the development version +Clang 20, 21, 22-git latest two stable releases per `LLVM's release page <https://releases.llvm.org>`_ and the development version AppleClang 26.0 latest stable release per `Xcode's release page <https://developer.apple.com/documentation/xcode-release-notes>`_ Open XL 17.1.3 (AIX) latest stable release per `Open XL's documentation page <https://www.ibm.com/docs/en/openxl-c-and-cpp-aix>`_ GCC 15 In C++11 or later only latest stable release per `GCC's release page <https://gcc.gnu.org/releases.html>`_ diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index de9819c..57032ce 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -878,6 +878,7 @@ set(files __type_traits/is_valid_expansion.h __type_traits/is_void.h __type_traits/is_volatile.h + __type_traits/is_within_lifetime.h __type_traits/lazy.h __type_traits/make_32_64_or_128_bit.h __type_traits/make_const_lvalue_ref.h diff --git a/libcxx/include/__configuration/compiler.h b/libcxx/include/__configuration/compiler.h index 11c07ed..7cd81e0 100644 --- a/libcxx/include/__configuration/compiler.h +++ b/libcxx/include/__configuration/compiler.h @@ -33,16 +33,16 @@ // Warn if a compiler version is used that is not supported anymore // LLVM RELEASE Update the minimum compiler versions # if defined(_LIBCPP_CLANG_VER) -# if _LIBCPP_CLANG_VER < 1900 -# warning "Libc++ only supports Clang 19 and later" +# if _LIBCPP_CLANG_VER < 2001 +# warning "Libc++ only supports Clang 20 and later" # endif # elif defined(_LIBCPP_APPLE_CLANG_VER) -# if _LIBCPP_APPLE_CLANG_VER < 1600 -# warning "Libc++ only supports AppleClang 15 and later" +# if _LIBCPP_APPLE_CLANG_VER < 1700 +# warning "Libc++ only supports AppleClang 26 and later" # endif # elif defined(_LIBCPP_GCC_VER) -# if _LIBCPP_GCC_VER < 1400 -# warning "Libc++ only supports GCC 14 and later" +# if _LIBCPP_GCC_VER < 1500 +# warning "Libc++ only supports GCC 15 and later" # endif # endif diff --git a/libcxx/include/__flat_set/flat_multiset.h b/libcxx/include/__flat_set/flat_multiset.h index 7be0b2d..0f6bae5 100644 --- a/libcxx/include/__flat_set/flat_multiset.h +++ b/libcxx/include/__flat_set/flat_multiset.h @@ -95,16 +95,16 @@ public: public: // [flat.multiset.cons], constructors - _LIBCPP_HIDE_FROM_ABI flat_multiset() noexcept(is_nothrow_default_constructible_v<_KeyContainer> && - is_nothrow_default_constructible_v<_Compare>) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset() noexcept( + is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_Compare>) : __keys_(), __compare_() {} - _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(const flat_multiset&) = default; // The copy/move constructors are not specified in the spec, which means they should be defaulted. // However, the move constructor can potentially leave a moved-from object in an inconsistent // state if an exception is thrown. - _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(flat_multiset&& __other) noexcept( is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>) # if _LIBCPP_HAS_EXCEPTIONS try @@ -121,14 +121,16 @@ public: # endif // _LIBCPP_HAS_EXCEPTIONS } - _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const key_compare& __comp) : __keys_(), __compare_(__comp) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_multiset(const key_compare& __comp) + : __keys_(), __compare_(__comp) {} - _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(container_type __keys, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_multiset(container_type __keys, const key_compare& __comp = key_compare()) : __keys_(std::move(__keys)), __compare_(__comp) { ranges::sort(__keys_, __compare_); } - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(sorted_equivalent_t, container_type __keys, const key_compare& __comp = key_compare()) : __keys_(std::move(__keys)), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); @@ -136,7 +138,7 @@ public: template <class _InputIterator> requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __keys_(), __compare_(__comp) { insert(__first, __last); @@ -144,48 +146,53 @@ public: template <class _InputIterator> requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset( sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare()) : __keys_(__first, __last), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); } template <_ContainerCompatibleRange<value_type> _Range> - _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t __fr, _Range&& __rg) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(from_range_t __fr, _Range&& __rg) : flat_multiset(__fr, std::forward<_Range>(__rg), key_compare()) {} template <_ContainerCompatibleRange<value_type> _Range> - _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multiset(__comp) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp) + : flat_multiset(__comp) { insert_range(std::forward<_Range>(__rg)); } - _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const key_compare& __comp = key_compare()) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(initializer_list<value_type> __il, const key_compare& __comp = key_compare()) : flat_multiset(__il.begin(), __il.end(), __comp) {} - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare()) : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp) {} template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_multiset(const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {} template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {} template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(const container_type& __keys, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(const container_type& __keys, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() { ranges::sort(__keys_, __compare_); } template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) { ranges::sort(__keys_, __compare_); @@ -193,14 +200,15 @@ public: template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, const container_type& __keys, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(sorted_equivalent_t, const container_type& __keys, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); } template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(sorted_equivalent_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); @@ -208,13 +216,14 @@ public: template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(const flat_multiset& __other, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __other.__keys_)), __compare_(__other.__compare_) {} template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(flat_multiset&& __other, const _Allocator& __alloc) # if _LIBCPP_HAS_EXCEPTIONS try # endif // _LIBCPP_HAS_EXCEPTIONS @@ -230,14 +239,15 @@ public: template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) - _LIBCPP_HIDE_FROM_ABI flat_multiset(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() { insert(__first, __last); } template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) { insert(__first, __last); @@ -245,7 +255,7 @@ public: template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_() { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); @@ -253,53 +263,57 @@ public: template <class _InputIterator, class _Allocator> requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value) - _LIBCPP_HIDE_FROM_ABI - flat_multiset(sorted_equivalent_t, - _InputIterator __first, - _InputIterator __last, - const key_compare& __comp, - const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset( + sorted_equivalent_t, + _InputIterator __first, + _InputIterator __last, + const key_compare& __comp, + const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_(__comp) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted"); } template <_ContainerCompatibleRange<value_type> _Range, class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(from_range_t, _Range&& __rg, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() { insert_range(std::forward<_Range>(__rg)); } template <_ContainerCompatibleRange<value_type> _Range, class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc) : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) { insert_range(std::forward<_Range>(__rg)); } template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(initializer_list<value_type> __il, const _Allocator& __alloc) : flat_multiset(__il.begin(), __il.end(), __alloc) {} template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc) : flat_multiset(__il.begin(), __il.end(), __comp, __alloc) {} template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 + flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc) : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __alloc) {} template <class _Allocator> requires uses_allocator<container_type, _Allocator>::value - _LIBCPP_HIDE_FROM_ABI flat_multiset( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset( sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc) : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {} - _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(initializer_list<value_type> __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset& operator=(initializer_list<value_type> __il) { clear(); insert(__il); return *this; @@ -308,9 +322,9 @@ public: // copy/move assignment are not specified in the spec (defaulted) // but move assignment can potentially leave moved from object in an inconsistent // state if an exception is thrown - _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(const flat_multiset&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset& operator=(const flat_multiset&) = default; - _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(flat_multiset&& __other) noexcept( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_multiset& operator=(flat_multiset&& __other) noexcept( is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) { auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; }); auto __clear_self_guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); @@ -321,30 +335,52 @@ public: } // iterators - _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return iterator(std::as_const(__keys_).begin()); } - _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return const_iterator(__keys_.begin()); } - _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return iterator(std::as_const(__keys_).end()); } - _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return const_iterator(__keys_.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept { + return iterator(std::as_const(__keys_).begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept { + return const_iterator(__keys_.begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept { + return iterator(std::as_const(__keys_).end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept { + return const_iterator(__keys_.end()); + } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } - _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); } - _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); } - _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(end()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(begin()); + } // capacity - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __keys_.empty(); } - _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __keys_.size(); } - _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { return __keys_.max_size(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept { + return __keys_.empty(); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { return __keys_.size(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return __keys_.max_size(); } // [flat.multiset.modifiers], modifiers template <class... _Args> requires is_constructible_v<value_type, _Args...> - _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace(_Args&&... __args) { if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) { return __emplace(std::forward<_Args>(__args)...); } else { @@ -354,7 +390,7 @@ public: template <class... _Args> requires is_constructible_v<value_type, _Args...> - _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) { if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) { return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...); } else { @@ -362,21 +398,23 @@ public: } } - _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const value_type& __x) { return emplace(__x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(value_type&& __x) { + return emplace(std::move(__x)); + } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) { return emplace_hint(__hint, __x); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) { return emplace_hint(__hint, std::move(__x)); } template <class _InputIterator> requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -385,7 +423,8 @@ public: template <class _InputIterator> requires __has_input_iterator_category<_InputIterator>::value - _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } @@ -394,7 +433,7 @@ public: } template <_ContainerCompatibleRange<value_type> _Range> - _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) { if constexpr (ranges::sized_range<_Range>) { __reserve(ranges::size(__range)); } @@ -402,26 +441,29 @@ public: __append_sort_merge</*WasSorted = */ false>(std::forward<_Range>(__range)); } - _LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list<value_type> __il) { + insert(__il.begin(), __il.end()); + } - _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list<value_type> __il) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + insert(sorted_equivalent_t, initializer_list<value_type> __il) { insert(sorted_equivalent, __il.begin(), __il.end()); } - _LIBCPP_HIDE_FROM_ABI container_type extract() && { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 container_type extract() && { auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; }); auto __ret = std::move(__keys_); return __ret; } - _LIBCPP_HIDE_FROM_ABI void replace(container_type&& __keys) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void replace(container_type&& __keys) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys, __compare_), "Key container is not sorted"); auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); __keys_ = std::move(__keys); __guard.__complete(); } - _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_iter = __keys_.erase(__position.__base()); __on_failure.__complete(); @@ -431,7 +473,7 @@ public: // The following overload is the same as the iterator overload // iterator erase(const_iterator __position); - _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); @@ -441,21 +483,21 @@ public: template <class _Kp> requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> && !is_convertible_v<_Kp &&, const_iterator>) - _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) { auto [__first, __last] = equal_range(__x); auto __res = __last - __first; erase(__first, __last); return __res; } - _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); auto __key_it = __keys_.erase(__first.__base(), __last.__base()); __on_failure.__complete(); return iterator(std::move(__key_it)); } - _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __y) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_multiset& __y) noexcept { // warning: The spec has unconditional noexcept, which means that // if any of the following functions throw an exception, // std::terminate will be called @@ -464,126 +506,139 @@ public: ranges::swap(__keys_, __y.__keys_); } - _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __keys_.clear(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __keys_.clear(); } // observers - _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; } - _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { return __compare_; } // map operations - _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) { + return __find_impl(*this, __x); + } - _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const { + return __find_impl(*this, __x); + } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) { return __find_impl(*this, __x); } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const { return __find_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const { auto [__first, __last] = equal_range(__x); return __last - __first; } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const { auto [__first, __last] = equal_range(__x); return __last - __first; } - _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const { + return find(__x) != end(); + } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const { return find(__x) != end(); } - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) { const auto& __keys = __keys_; return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const { return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) { const auto& __keys = __keys_; return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_)); } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const { return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) { const auto& __keys = __keys_; return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const { return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) { const auto& __keys = __keys_; return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_)); } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const { return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_)); } - _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const key_type& __x) { return __equal_range_impl(*this, __x); } - _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator> + equal_range(const key_type& __x) const { return __equal_range_impl(*this, __x); } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const _Kp& __x) { return __equal_range_impl(*this, __x); } template <class _Kp> requires __is_transparent_v<_Compare> - _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator> + equal_range(const _Kp& __x) const { return __equal_range_impl(*this, __x); } - friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multiset& __x, const flat_multiset& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator==(const flat_multiset& __x, const flat_multiset& __y) { return ranges::equal(__x, __y); } - friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multiset& __x, const flat_multiset& __y) { + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto + operator<=>(const flat_multiset& __x, const flat_multiset& __y) { return std::lexicographical_compare_three_way( __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way); } - friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __x, flat_multiset& __y) noexcept { __x.swap(__y); } + friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + swap(flat_multiset& __x, flat_multiset& __y) noexcept { + __x.swap(__y); + } private: template <bool _WasSorted, class... _Args> - _LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __append_sort_merge(_Args&&... __args) { auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; }); size_type __old_size = size(); __flat_set_utils::__append(*this, std::forward<_Args>(__args)...); @@ -598,13 +653,13 @@ private: } template <class _Kp> - _LIBCPP_HIDE_FROM_ABI iterator __emplace(_Kp&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace(_Kp&& __key) { auto __it = upper_bound(__key); return __flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key)); } template <class _Kp> - _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint(const_iterator __hint, _Kp&& __key) { auto __prev_larger = __hint != cbegin() && __compare_(__key, *std::prev(__hint)); auto __next_smaller = __hint != cend() && __compare_(*__hint, __key); @@ -636,7 +691,7 @@ private: } template <class _Self, class _Kp> - _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) { auto __it = __self.lower_bound(__key); auto __last = __self.end(); if (__it == __last || __self.__compare_(__key, *__it)) { @@ -646,29 +701,30 @@ private: } template <class _Self, class _Kp> - _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) { using __iter = _If<is_const_v<__libcpp_remove_reference_t<_Self>>, const_iterator, iterator>; auto [__key_first, __key_last] = std::equal_range(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_); return std::make_pair(__iter(__key_first), __iter(__key_last)); } - _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) { if constexpr (__container_traits<_KeyContainer>::__reservable) { __keys_.reserve(__size); } } template <class _Key2, class _Compare2, class _KeyContainer2, class _Predicate> - friend typename flat_multiset<_Key2, _Compare2, _KeyContainer2>::size_type + friend typename flat_multiset<_Key2, _Compare2, _KeyContainer2>::size_type _LIBCPP_CONSTEXPR_SINCE_CXX26 erase_if(flat_multiset<_Key2, _Compare2, _KeyContainer2>&, _Predicate); _KeyContainer __keys_; _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_; struct __key_equiv { - _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {} - _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + operator()(const_reference __x, const_reference __y) const { return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x)); } key_compare __comp_; @@ -757,7 +813,7 @@ struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Allocator> : bool_constant<uses_allocator_v<_KeyContainer, _Allocator> > {}; template <class _Key, class _Compare, class _KeyContainer, class _Predicate> -_LIBCPP_HIDE_FROM_ABI typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __flat_multiset, _Predicate __pred) { auto __guard = std::__make_exception_guard([&] { __flat_multiset.clear(); }); auto __it = diff --git a/libcxx/include/__functional/identity.h b/libcxx/include/__functional/identity.h index 1b1c6cf..02dde2b 100644 --- a/libcxx/include/__functional/identity.h +++ b/libcxx/include/__functional/identity.h @@ -44,7 +44,7 @@ struct __is_identity<reference_wrapper<const __identity> > : true_type {}; struct identity { template <class _Tp> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_LIBCPP_LIFETIMEBOUND _Tp&& __t) const noexcept { return std::forward<_Tp>(__t); } diff --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h index 6582691..5378c03 100644 --- a/libcxx/include/__memory/construct_at.h +++ b/libcxx/include/__memory/construct_at.h @@ -14,7 +14,6 @@ #include <__config> #include <__memory/addressof.h> #include <__new/placement_new_delete.h> -#include <__type_traits/enable_if.h> #include <__type_traits/is_array.h> #include <__utility/declval.h> #include <__utility/forward.h> @@ -55,35 +54,25 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* __construct_at(_Tp* __l // The internal functions are available regardless of the language version (with the exception of the `__destroy_at` // taking an array). -template <class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0> +template <class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) { _LIBCPP_ASSERT_NON_NULL(__loc != nullptr, "null pointer given to destroy_at"); - __loc->~_Tp(); -} - #if _LIBCPP_STD_VER >= 20 -template <class _Tp, __enable_if_t<is_array<_Tp>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI constexpr void __destroy_at(_Tp* __loc) { - _LIBCPP_ASSERT_NON_NULL(__loc != nullptr, "null pointer given to destroy_at"); - for (auto&& __val : *__loc) - std::__destroy_at(std::addressof(__val)); -} + if constexpr (is_array_v<_Tp>) { + for (auto&& __val : *__loc) + std::__destroy_at(std::addressof(__val)); + } else #endif + { + __loc->~_Tp(); + } +} #if _LIBCPP_STD_VER >= 17 - -template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0> +template <class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) { std::__destroy_at(__loc); } - -# if _LIBCPP_STD_VER >= 20 -template <class _Tp, enable_if_t<is_array_v<_Tp>, int> = 0> -_LIBCPP_HIDE_FROM_ABI constexpr void destroy_at(_Tp* _LIBCPP_DIAGNOSE_NULLPTR __loc) { - std::__destroy_at(__loc); -} -# endif - #endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_within_lifetime.h b/libcxx/include/__type_traits/is_within_lifetime.h new file mode 100644 index 0000000..242f2ad --- /dev/null +++ b/libcxx/include/__type_traits/is_within_lifetime.h @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___TYPE_TRAITS_IS_WITHIN_LIFETIME_H +#define _LIBCPP___TYPE_TRAITS_IS_WITHIN_LIFETIME_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_is_within_lifetime) +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI consteval bool is_within_lifetime(const _Tp* __p) noexcept { + return __builtin_is_within_lifetime(__p); +} +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_IS_WITHIN_LIFETIME_H diff --git a/libcxx/include/deque b/libcxx/include/deque index 3e7ee8d85..ab41b9d 100644 --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -193,7 +193,6 @@ template <class T, class Allocator, class Predicate> # include <__algorithm/move_backward.h> # include <__algorithm/remove.h> # include <__algorithm/remove_if.h> -# include <__algorithm/unwrap_iter.h> # include <__assert> # include <__config> # include <__debug_utils/sanitizers.h> @@ -220,11 +219,9 @@ template <class T, class Allocator, class Predicate> # include <__ranges/concepts.h> # include <__ranges/container_compatible_range.h> # include <__ranges/from_range.h> -# include <__ranges/size.h> # include <__split_buffer> # include <__type_traits/conditional.h> # include <__type_traits/container_traits.h> -# include <__type_traits/disjunction.h> # include <__type_traits/enable_if.h> # include <__type_traits/is_allocator.h> # include <__type_traits/is_convertible.h> diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index 88d863f..272e52d 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -223,14 +223,12 @@ template <class T, class Allocator, class Predicate> # include <__ranges/concepts.h> # include <__ranges/container_compatible_range.h> # include <__ranges/from_range.h> -# include <__type_traits/conditional.h> # include <__type_traits/container_traits.h> # include <__type_traits/enable_if.h> # include <__type_traits/is_allocator.h> # include <__type_traits/is_const.h> # include <__type_traits/is_nothrow_assignable.h> # include <__type_traits/is_nothrow_constructible.h> -# include <__type_traits/is_pointer.h> # include <__type_traits/is_same.h> # include <__type_traits/is_swappable.h> # include <__type_traits/remove_cv.h> diff --git a/libcxx/include/list b/libcxx/include/list index 0ff85d2..2898a45 100644 --- a/libcxx/include/list +++ b/libcxx/include/list @@ -228,13 +228,11 @@ template <class T, class Allocator, class Predicate> # include <__ranges/concepts.h> # include <__ranges/container_compatible_range.h> # include <__ranges/from_range.h> -# include <__type_traits/conditional.h> # include <__type_traits/container_traits.h> # include <__type_traits/enable_if.h> # include <__type_traits/is_allocator.h> # include <__type_traits/is_nothrow_assignable.h> # include <__type_traits/is_nothrow_constructible.h> -# include <__type_traits/is_pointer.h> # include <__type_traits/is_same.h> # include <__type_traits/type_identity.h> # include <__utility/exception_guard.h> diff --git a/libcxx/include/map b/libcxx/include/map index 3ff849a..cc8b876 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -600,9 +600,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20 # include <__ranges/from_range.h> # include <__tree> # include <__type_traits/container_traits.h> -# include <__type_traits/desugars_to.h> # include <__type_traits/is_allocator.h> -# include <__type_traits/is_convertible.h> # include <__type_traits/make_transparent.h> # include <__type_traits/remove_const.h> # include <__type_traits/type_identity.h> diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 11ab61d..24a2fe7 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -350,6 +350,7 @@ module std_core [system] { header "__type_traits/is_volatile.h" export std_core.type_traits.integral_constant } + module is_within_lifetime { header "__type_traits/is_within_lifetime.h" } module lazy { header "__type_traits/lazy.h" } module make_32_64_or_128_bit { header "__type_traits/make_32_64_or_128_bit.h" } module make_const_lvalue_ref { header "__type_traits/make_const_lvalue_ref.h" } diff --git a/libcxx/include/set b/libcxx/include/set index 59ed015..d58b6e9 100644 --- a/libcxx/include/set +++ b/libcxx/include/set @@ -524,7 +524,6 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20 # include <__functional/operations.h> # include <__iterator/erase_if_container.h> # include <__iterator/iterator_traits.h> -# include <__iterator/ranges_iterator_traits.h> # include <__iterator/reverse_iterator.h> # include <__memory/allocator.h> # include <__memory/allocator_traits.h> @@ -538,7 +537,6 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20 # include <__type_traits/container_traits.h> # include <__type_traits/enable_if.h> # include <__type_traits/is_allocator.h> -# include <__type_traits/is_nothrow_assignable.h> # include <__type_traits/is_nothrow_constructible.h> # include <__type_traits/is_same.h> # include <__type_traits/is_swappable.h> diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index a6e0c18..dab0c06 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -454,6 +454,10 @@ namespace std template<class B> inline constexpr bool negation_v = negation<B>::value; // since C++17 + // [meta.const.eval], constant evaluation context + constexpr bool is_constant_evaluated() noexcept; // C++20 + template<class T> + consteval bool is_within_lifetime(const T*) noexcept; // C++26 } */ @@ -559,6 +563,10 @@ namespace std # include <__type_traits/reference_converts_from_temporary.h> # endif +# if _LIBCPP_STD_VER >= 26 +# include <__type_traits/is_within_lifetime.h> +# endif + # include <version> # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set index 4d0e2ac..9873f1e 100644 --- a/libcxx/include/unordered_set +++ b/libcxx/include/unordered_set @@ -544,8 +544,6 @@ template <class Value, class Hash, class Pred, class Alloc> # include <__iterator/distance.h> # include <__iterator/erase_if_container.h> # include <__iterator/iterator_traits.h> -# include <__iterator/ranges_iterator_traits.h> -# include <__memory/addressof.h> # include <__memory/allocator.h> # include <__memory/allocator_traits.h> # include <__memory_resource/polymorphic_allocator.h> @@ -558,7 +556,6 @@ template <class Value, class Hash, class Pred, class Alloc> # include <__type_traits/invoke.h> # include <__type_traits/is_allocator.h> # include <__type_traits/is_integral.h> -# include <__type_traits/is_nothrow_assignable.h> # include <__type_traits/is_nothrow_constructible.h> # include <__type_traits/is_same.h> # include <__type_traits/is_swappable.h> diff --git a/libcxx/include/version b/libcxx/include/version index 0fef1bb..b003060 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -71,6 +71,8 @@ __cpp_lib_constexpr_charconv 202207L <charconv> __cpp_lib_constexpr_cmath 202202L <cmath> <cstdlib> __cpp_lib_constexpr_complex 201711L <complex> __cpp_lib_constexpr_dynamic_alloc 201907L <memory> +__cpp_lib_constexpr_flat_map 202502L <flat_map> +__cpp_lib_constexpr_flat_set 202502L <flat_set> __cpp_lib_constexpr_forward_list 202502L <forward_list> __cpp_lib_constexpr_functional 201907L <functional> __cpp_lib_constexpr_iterator 201811L <iterator> @@ -552,6 +554,8 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_bitset 202306L # undef __cpp_lib_constexpr_algorithms # define __cpp_lib_constexpr_algorithms 202306L +# define __cpp_lib_constexpr_flat_map 202502L +# define __cpp_lib_constexpr_flat_set 202502L # define __cpp_lib_constexpr_forward_list 202502L # define __cpp_lib_constexpr_list 202502L # if !defined(_LIBCPP_ABI_VCRUNTIME) @@ -582,7 +586,9 @@ __cpp_lib_void_t 201411L <type_traits> # if __has_builtin(__builtin_is_virtual_base_of) # define __cpp_lib_is_virtual_base_of 202406L # endif -// # define __cpp_lib_is_within_lifetime 202306L +# if __has_builtin(__builtin_is_within_lifetime) +# define __cpp_lib_is_within_lifetime 202306L +# endif // # define __cpp_lib_linalg 202311L # undef __cpp_lib_mdspan # define __cpp_lib_mdspan 202406L diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc index 6823c86..4e49ed8 100644 --- a/libcxx/modules/std/type_traits.inc +++ b/libcxx/modules/std/type_traits.inc @@ -330,6 +330,9 @@ export namespace std { // [meta.const.eval], constant evaluation context using std::is_constant_evaluated; +#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_is_within_lifetime) + using std::is_within_lifetime; +#endif // [depr.meta.types] using std::aligned_storage; diff --git a/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert.temporary.pass.cpp b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert.temporary.pass.cpp index 248f282..acd20ce 100644 --- a/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert.temporary.pass.cpp +++ b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert.temporary.pass.cpp @@ -21,7 +21,7 @@ #include "../flat_helpers.h" #include "test_macros.h" -bool test() { +constexpr bool test() { using M = std::flat_multiset<TrackCopyMove>; { M m; @@ -43,6 +43,9 @@ bool test() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp index 57a581c..c2fcd86 100644 --- a/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp +++ b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp @@ -20,27 +20,36 @@ #include <cassert> #include <flat_set> #include <ranges> -#include <sstream> #include <vector> #include "../flat_helpers.h" +#include "test_iterators.h" #include "test_macros.h" -void test() { +constexpr bool test() { NotQuiteSequenceContainer<int> v; std::flat_multiset s(v); - std::istringstream ints("0 1 1 0"); - auto r = std::ranges::subrange(std::istream_iterator<int>(ints), std::istream_iterator<int>()) | - std::views::transform([](int i) { return i * i; }); + + int ar[] = {0, 1, 1, 0}; + using Iter = cpp20_input_iterator<const int*>; + using Sent = sentinel_wrapper<Iter>; + using R = std::ranges::subrange<Iter, Sent>; + auto r = R(Iter(ar), Sent(Iter(ar + 4))); + static_assert(  { return requires { t.insert_range(t.end(), r); }; }(v), "This test is to test the case where the underlying container does not provide insert_range"); s.insert_range(r); assert(std::ranges::equal(s, std::vector<int>{0, 0, 1, 1})); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/libcxx/utilities/function.objects/lifetimebound.verify.cpp b/libcxx/test/libcxx/utilities/function.objects/lifetimebound.verify.cpp new file mode 100644 index 0000000..5c66bc1 --- /dev/null +++ b/libcxx/test/libcxx/utilities/function.objects/lifetimebound.verify.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++11, c++14, c++17 +// ADDITIONAL_COMPILE_FLAGS: -Wno-pessimizing-move -Wno-unused-variable + +#include <functional> + +#include "test_macros.h" + +// clang-format off + +void func() { + auto&& v1 = std::identity()(1); // expected-warning {{temporary bound to local reference 'v1' will be destroyed at the end of the full-expression}} +} diff --git a/libcxx/test/libcxx/utilities/meta/is_within_lifetime.verify.cpp b/libcxx/test/libcxx/utilities/meta/is_within_lifetime.verify.cpp new file mode 100644 index 0000000..ff3ecfb --- /dev/null +++ b/libcxx/test/libcxx/utilities/meta/is_within_lifetime.verify.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++11, c++14, c++17, c++20, c++23 +// UNSUPPORTED: gcc-15, apple-clang-17 + +// <type_traits> + +// LWG4138 <https://cplusplus.github.io/LWG/issue4138> +// std::is_within_lifetime shouldn't work when a function type is +// explicitly specified, even if it isn't evaluated + +#include <type_traits> + +template <class T> +consteval bool checked_is_within_lifetime(T* p) { + return p ? std::is_within_lifetime<T>(p) : false; +} +static_assert(!checked_is_within_lifetime<int>(nullptr)); +static_assert(!checked_is_within_lifetime<void()>(nullptr)); +// expected-error@*:* {{function pointer argument to '__builtin_is_within_lifetime' is not allowed}} diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/empty.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/empty.pass.cpp index 52f7743..88a76d3 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/empty.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/empty.pass.cpp @@ -24,7 +24,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<int>, KeyContainer>; M m; @@ -38,15 +38,23 @@ void test_one() { assert(m.empty()); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/max_size.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/max_size.pass.cpp index 4e3d141..fb9c38f 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/max_size.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/max_size.pass.cpp @@ -24,7 +24,7 @@ #include "test_allocator.h" #include "test_macros.h" -void test() { +constexpr bool test() { { using A1 = limited_allocator<int, 10>; using C = std::flat_multiset<int, std::less<int>, std::vector<int, A1>>; @@ -59,10 +59,15 @@ void test() { assert(c.max_size() <= max_dist); assert(c.max_size() <= alloc_max_size(std::allocator<char>())); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/size.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/size.pass.cpp index 4aff08b..156bb27 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/size.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.capacity/size.pass.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=200000000 +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=800000000 // <flat_set> @@ -23,7 +25,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using M = std::flat_multiset<int, std::less<int>, KeyContainer>; using S = typename M::size_type; { @@ -46,7 +48,7 @@ void test_one() { } { M m; - S s = 500000; + S s = 5000; for (std::size_t i = 0u; i < s; ++i) { m.emplace(i); m.emplace(i); @@ -57,15 +59,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/alloc.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/alloc.pass.cpp index 4fffcb3..2426fbc 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/alloc.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/alloc.pass.cpp @@ -14,6 +14,7 @@ // explicit flat_multiset(const Allocator& a); #include <cassert> +#include <deque> #include <flat_set> #include <functional> #include <vector> @@ -22,7 +23,8 @@ #include "test_allocator.h" #include "../../../test_compare.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true @@ -30,8 +32,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; static_assert(std::is_constructible_v<M1, const A1&>); @@ -40,24 +42,37 @@ void test() { static_assert(!std::is_constructible_v<M2, const A1&>); } { - // explicit - using M = std::flat_multiset<int, std::less<int>, std::vector<int, test_allocator<int>>>; - - static_assert(std::is_constructible_v<M, test_allocator<int>>); - static_assert(!std::is_convertible_v<test_allocator<int>, M>); - } - { using A = test_allocator<short>; - using M = std::flat_multiset<int, std::less<int>, std::vector<int, test_allocator<int>>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, test_allocator<int>>>; M m(A(0, 5)); assert(m.empty()); assert(m.begin() == m.end()); assert(std::move(m).extract().get_allocator().get_id() == 5); } + { + // explicit + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, test_allocator<int>>>; + + static_assert(std::is_constructible_v<M, test_allocator<int>>); + static_assert(!std::is_convertible_v<test_allocator<int>, M>); + } +} + +constexpr bool test() { + test<std::vector>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/assign_initializer_list.pass.cpp index ae81ab0..a895117 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/assign_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/assign_initializer_list.pass.cpp @@ -26,7 +26,7 @@ #include "test_allocator.h" template <class KeyContainer> -void test() { +constexpr void test() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; { @@ -53,16 +53,24 @@ void test() { } } -void test() { +constexpr bool test() { test<std::vector<int>>(); test<std::vector<double>>(); - test<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque<int>>(); test<MinSequenceContainer<int>>(); test<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/compare.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/compare.pass.cpp index 6b68589..43ebea7 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/compare.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/compare.pass.cpp @@ -20,11 +20,35 @@ #include <type_traits> #include <vector> +#include "MinSequenceContainer.h" +#include "min_allocator.h" #include "test_macros.h" #include "../../../test_compare.h" #include "test_allocator.h" -void test() { +template <class KeyContainer> +constexpr void test_compare() { + using Key = typename KeyContainer::value_type; + { + // The one-argument ctor is explicit. + using C = test_less<Key>; + static_assert(std::is_constructible_v<std::flat_multiset<Key, C>, C>); + static_assert(!std::is_convertible_v<C, std::flat_multiset<Key, C>>); + + static_assert(std::is_constructible_v<std::flat_multiset<Key>, std::less<Key>>); + static_assert(!std::is_convertible_v<std::less<Key>, std::flat_multiset<Key>>); + } + { + using C = test_less<Key>; + auto m = std::flat_multiset<Key, C>(C(3)); + assert(m.empty()); + assert(m.begin() == m.end()); + assert(m.key_comp() == C(3)); + } +} + +template <template <class...> class KeyContainer> +constexpr void test_compare_alloc() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true @@ -32,8 +56,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; static_assert(std::is_constructible_v<M1, const C&, const A1&>); @@ -42,25 +66,9 @@ void test() { static_assert(!std::is_constructible_v<M2, const C&, const A1&>); } { - using C = test_less<int>; - auto m = std::flat_multiset<int, C>(C(3)); - assert(m.empty()); - assert(m.begin() == m.end()); - assert(m.key_comp() == C(3)); - } - { - // The one-argument ctor is explicit. - using C = test_less<int>; - static_assert(std::is_constructible_v<std::flat_multiset<int, C>, C>); - static_assert(!std::is_convertible_v<C, std::flat_multiset<int, C>>); - - static_assert(std::is_constructible_v<std::flat_multiset<int>, std::less<int>>); - static_assert(!std::is_convertible_v<std::less<int>, std::flat_multiset<int>>); - } - { using C = test_less<int>; using A1 = test_allocator<int>; - auto m = std::flat_multiset<int, C, std::vector<int, A1>>(C(4), A1(5)); + auto m = std::flat_multiset<int, C, KeyContainer<int, A1>>(C(4), A1(5)); assert(m.empty()); assert(m.begin() == m.end()); assert(m.key_comp() == C(4)); @@ -68,9 +76,9 @@ void test() { } { // explicit(false) - using C = test_less<int>; - using A1 = test_allocator<int>; - std::flat_multiset<int, C, std::deque<int, A1>> m = {C(4), A1(5)}; + using C = test_less<int>; + using A1 = test_allocator<int>; + std::flat_multiset<int, C, KeyContainer<int, A1>> m = {C(4), A1(5)}; assert(m.empty()); assert(m.begin() == m.end()); assert(m.key_comp() == C(4)); @@ -78,8 +86,29 @@ void test() { } } +constexpr bool test() { + test_compare<std::vector<int>>(); + test_compare<MinSequenceContainer<int>>(); + test_compare<std::vector<int, min_allocator<int>>>(); + + test_compare_alloc<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + test_compare<std::deque<int>>(); + test_compare_alloc<std::deque>(); + } + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/containers.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/containers.pass.cpp index 78eac42..1a47600 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/containers.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/containers.pass.cpp @@ -35,7 +35,8 @@ void conversion_test(T); template <class T, class... Args> concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); }; -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true @@ -43,8 +44,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; static_assert(std::is_constructible_v<M1, const V1&, const A1&>); @@ -59,15 +60,15 @@ void test() { } { // flat_multiset(container_type) - using M = std::flat_multiset<int>; - std::vector<int> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3}; - auto m = M(ks); - int expected[] = {1, 1, 1, 2, 2, 2, 3, 3, 3}; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; + KeyContainer<int> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3}; + auto m = M(ks); + int expected[] = {1, 1, 1, 2, 2, 2, 3, 3, 3}; assert(std::ranges::equal(m, expected)); // explicit(false) - static_assert(std::is_constructible_v<M, const std::vector<int>&>); - static_assert(!ImplicitlyConstructible<M, const std::vector<int>&>); + static_assert(std::is_constructible_v<M, const KeyContainer<int>&>); + static_assert(!ImplicitlyConstructible<M, const KeyContainer<int>&>); m = M(std::move(ks)); assert(ks.empty()); // it was moved-from @@ -77,7 +78,7 @@ void test() { // flat_multiset(container_type) // move-only int expected[] = {3, 3, 2, 1}; - using Ks = std::deque<MoveOnly, min_allocator<MoveOnly>>; + using Ks = KeyContainer<MoveOnly, min_allocator<MoveOnly>>; using M = std::flat_multiset<MoveOnly, std::greater<MoveOnly>, Ks>; Ks ks; ks.push_back(1); @@ -92,8 +93,8 @@ void test() { // flat_multiset(container_type) // container's allocators are used using A = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::deque<int, A>>; - auto ks = std::deque<int, A>({1, 1, 1, 2, 2, 3, 2, 3, 3}, A(5)); + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A>>; + auto ks = KeyContainer<int, A>({1, 1, 1, 2, 2, 3, 2, 3, 3}, A(5)); auto m = M(std::move(ks)); assert(ks.empty()); // it was moved-from assert((m == M{1, 1, 1, 2, 2, 2, 3, 3, 3})); @@ -102,22 +103,22 @@ void test() { } { // flat_multiset(container_type, key_compare) - using C = test_less<int>; - using M = std::flat_multiset<int, C>; - std::vector<int> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3}; - auto m = M(ks, C(4)); + using C = test_less<int>; + using M = std::flat_multiset<int, C, KeyContainer<int>>; + KeyContainer<int> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3}; + auto m = M(ks, C(4)); assert(std::ranges::equal(m, std::vector<int>{1, 1, 1, 2, 2, 2, 3, 3, 3})); assert(m.key_comp() == C(4)); // explicit - static_assert(std::is_constructible_v<M, const std::vector<int>&, const C&>); - static_assert(!ImplicitlyConstructible<M, const std::vector<int>&, const C&>); + static_assert(std::is_constructible_v<M, const KeyContainer<int>&, const C&>); + static_assert(!ImplicitlyConstructible<M, const KeyContainer<int>&, const C&>); } { // flat_multiset(container_type , const Allocator&) using A = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::deque<int, A>>; - auto ks = std::deque<int, A>({1, 1, 1, 2, 2, 3, 2, 3, 3}, A(5)); + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A>>; + auto ks = KeyContainer<int, A>({1, 1, 1, 2, 2, 3, 2, 3, 3}, A(5)); auto m = M(ks, A(4)); // replaces the allocators assert(!ks.empty()); // it was an lvalue above assert((m == M{1, 1, 1, 2, 2, 2, 3, 3, 3})); @@ -125,7 +126,7 @@ void test() { assert(keys.get_allocator() == A(4)); // explicit(false) - static_assert(ImplicitlyConstructible<M, const std::deque<int, A>&, const A&>); + static_assert(ImplicitlyConstructible<M, const KeyContainer<int, A>&, const A&>); M m2 = {ks, A(4)}; // implicit ctor assert(!ks.empty()); // it was an lvalue above assert(m2 == m); @@ -134,19 +135,19 @@ void test() { } { // flat_multiset(container_type , const Allocator&) - using C = test_less<int>; - using A = test_allocator<int>; - using M = std::flat_multiset<int, C, std::vector<int, A>>; - std::vector<int, A> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3}; - auto m = M(ks, C(4), A(5)); - assert(std::ranges::equal(m, std::vector<int, A>{1, 1, 1, 2, 2, 2, 3, 3, 3})); + using C = test_less<int>; + using A = test_allocator<int>; + using M = std::flat_multiset<int, C, KeyContainer<int, A>>; + KeyContainer<int, A> ks = {1, 1, 1, 2, 2, 3, 2, 3, 3}; + auto m = M(ks, C(4), A(5)); + assert(std::ranges::equal(m, KeyContainer<int, A>{1, 1, 1, 2, 2, 2, 3, 3, 3})); assert(m.key_comp() == C(4)); auto m_copy = m; auto keys = std::move(m_copy).extract(); assert(keys.get_allocator() == A(5)); // explicit(false) - static_assert(ImplicitlyConstructible<M, const std::vector<int, A>&, const A&>); + static_assert(ImplicitlyConstructible<M, const KeyContainer<int, A>&, const A&>); M m2 = {ks, C(4), A(5)}; assert(m2 == m); assert(m2.key_comp() == C(4)); @@ -155,8 +156,22 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy.pass.cpp index b4f7220..55f3def 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy.pass.cpp @@ -14,6 +14,7 @@ #include <algorithm> #include <cassert> +#include <deque> #include <flat_set> #include <vector> @@ -21,10 +22,11 @@ #include "../../../test_compare.h" #include "test_allocator.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { using C = test_less<int>; - std::vector<int, test_allocator<int>> ks({1, 3, 5, 3, 1}, test_allocator<int>(6)); + KeyContainer<int, test_allocator<int>> ks({1, 3, 5, 3, 1}, test_allocator<int>(6)); const int expected[] = {1, 1, 3, 3, 5}; using M = std::flat_multiset<int, C, decltype(ks)>; auto mo = M(ks, C(5)); @@ -43,7 +45,7 @@ void test() { } { using C = test_less<int>; - using Ks = std::vector<int, other_allocator<int>>; + using Ks = KeyContainer<int, other_allocator<int>>; auto ks = Ks({1, 3, 5, 3, 1}, other_allocator<int>(6)); const int expected[] = {1, 1, 3, 3, 5}; using M = std::flat_multiset<int, C, Ks>; @@ -63,8 +65,22 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_alloc.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_alloc.pass.cpp index ec8ad82..ec9f14e 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_alloc.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_alloc.pass.cpp @@ -23,7 +23,8 @@ #include "../../../test_compare.h" #include "test_allocator.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -31,8 +32,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; static_assert(std::is_constructible_v<M1, const M1&, const A1&>); @@ -42,7 +43,7 @@ void test() { } { using C = test_less<int>; - std::vector<int, test_allocator<int>> ks({1, 3, 5, 5}, test_allocator<int>(6)); + KeyContainer<int, test_allocator<int>> ks({1, 3, 5, 5}, test_allocator<int>(6)); using M = std::flat_multiset<int, C, decltype(ks)>; auto mo = M(ks, C(5)); auto m = M(mo, test_allocator<int>(3)); @@ -59,8 +60,23 @@ void test() { assert(keys2.get_allocator() == test_allocator<int>(6)); } } + +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_assign.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_assign.pass.cpp index 2b6176a..2e63a00 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_assign.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/copy_assign.pass.cpp @@ -13,6 +13,7 @@ // flat_multiset& operator=(const flat_multiset& m); #include <algorithm> +#include <deque> #include <flat_set> #include <functional> #include <vector> @@ -22,11 +23,12 @@ #include "../../../test_compare.h" #include "test_allocator.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // test_allocator is not propagated using C = test_less<int>; - std::vector<int, test_allocator<int>> ks({1, 3, 5, 5}, test_allocator<int>(6)); + KeyContainer<int, test_allocator<int>> ks({1, 3, 5, 5}, test_allocator<int>(6)); using M = std::flat_multiset<int, C, decltype(ks)>; auto mo = M(ks, C(5)); auto m = M({{3, 4, 5, 4}}, C(3), test_allocator<int>(2)); @@ -46,7 +48,7 @@ void test() { { // other_allocator is propagated using C = test_less<int>; - using Ks = std::vector<int, other_allocator<int>>; + using Ks = KeyContainer<int, other_allocator<int>>; auto ks = Ks({1, 3, 5, 3}, other_allocator<int>(6)); const int expected[] = {1, 3, 3, 5}; using M = std::flat_multiset<int, C, Ks>; @@ -65,7 +67,7 @@ void test() { auto keys2 = std::move(mo).extract(); assert(keys2.get_allocator() == other_allocator<int>(6)); } - { + if (!TEST_IS_CONSTANT_EVALUATED) { // comparator is copied and invariant is preserved using M = std::flat_multiset<int, std::function<bool(int, int)>>; M mo = M({1, 2}, std::less<int>()); @@ -103,8 +105,22 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/default.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/default.pass.cpp index 16f9032..3a7ff86 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/default.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/default.pass.cpp @@ -25,28 +25,29 @@ #include "test_macros.h" struct DefaultCtableComp { - explicit DefaultCtableComp() { default_constructed_ = true; } - bool operator()(int, int) const { return false; } + constexpr explicit DefaultCtableComp() { default_constructed_ = true; } + constexpr bool operator()(int, int) const { return false; } bool default_constructed_ = false; }; struct ThrowingCtorComp { - ThrowingCtorComp() noexcept(false) {} - bool operator()(const auto&, const auto&) const { return false; } + constexpr ThrowingCtorComp() noexcept(false) {} + constexpr bool operator()(const auto&, const auto&) const { return false; } }; -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { - std::flat_multiset<int> m; + std::flat_multiset<int, std::less<int>, KeyContainer<int>> m; assert(m.empty()); } { // explicit(false) - std::flat_multiset<int> m = {}; + std::flat_multiset<int, std::less<int>, KeyContainer<int>> m = {}; assert(m.empty()); } { - std::flat_multiset<int, DefaultCtableComp, std::deque<int, min_allocator<int>>> m; + std::flat_multiset<int, DefaultCtableComp, KeyContainer<int, min_allocator<int>>> m; assert(m.empty()); assert(m.begin() == m.end()); assert(m.key_comp().default_constructed_); @@ -54,7 +55,7 @@ void test() { { using A1 = explicit_allocator<int>; { - std::flat_multiset<int, DefaultCtableComp, std::vector<int, A1>> m; + std::flat_multiset<int, DefaultCtableComp, KeyContainer<int, A1>> m; assert(m.empty()); assert(m.key_comp().default_constructed_); } @@ -67,30 +68,46 @@ void test() { } #if defined(_LIBCPP_VERSION) { - using C = std::flat_multiset<MoveOnly>; + using C = std::flat_multiset<MoveOnly, std::less<MoveOnly>>; static_assert(std::is_nothrow_default_constructible_v<C>); C c; } { - using C = std::flat_multiset<MoveOnly, std::less<MoveOnly>, std::vector<MoveOnly, test_allocator<MoveOnly>>>; + using C = std::flat_multiset<MoveOnly, std::less<MoveOnly>, KeyContainer<MoveOnly, test_allocator<MoveOnly>>>; static_assert(std::is_nothrow_default_constructible_v<C>); C c; } #endif // _LIBCPP_VERSION { - using C = std::flat_multiset<MoveOnly, std::less<MoveOnly>, std::vector<MoveOnly, other_allocator<MoveOnly>>>; + using C = std::flat_multiset<MoveOnly, std::less<MoveOnly>, KeyContainer<MoveOnly, other_allocator<MoveOnly>>>; static_assert(!std::is_nothrow_default_constructible_v<C>); C c; } { - using C = std::flat_multiset<MoveOnly, ThrowingCtorComp>; + using C = std::flat_multiset<MoveOnly, ThrowingCtorComp, KeyContainer<MoveOnly>>; static_assert(!std::is_nothrow_default_constructible_v<C>); C c; } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + test<std::deque>(); + } + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/dtor_noexcept.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/dtor_noexcept.pass.cpp index f852f2f..f7243fa 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/dtor_noexcept.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/dtor_noexcept.pass.cpp @@ -23,39 +23,56 @@ #include "test_allocator.h" struct ThrowingDtorComp { - bool operator()(const auto&, const auto&) const; - ~ThrowingDtorComp() noexcept(false) {} + constexpr bool operator()(const auto&, const auto&) const; + constexpr ~ThrowingDtorComp() noexcept(false) {} }; -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { - using C = std::flat_multiset<MoveOnly, MoveOnly>; + using C = std::flat_multiset<MoveOnly, std::less<MoveOnly>, KeyContainer<MoveOnly>>; static_assert(std::is_nothrow_destructible_v<C>); C c; } { - using V = std::vector<MoveOnly, test_allocator<MoveOnly>>; + using V = KeyContainer<MoveOnly, test_allocator<MoveOnly>>; using C = std::flat_multiset<MoveOnly, std::less<MoveOnly>, V>; static_assert(std::is_nothrow_destructible_v<C>); C c; } { - using V = std::deque<MoveOnly, other_allocator<MoveOnly>>; + using V = KeyContainer<MoveOnly, other_allocator<MoveOnly>>; using C = std::flat_multiset<MoveOnly, std::greater<MoveOnly>, V>; static_assert(std::is_nothrow_destructible_v<C>); C c; } #if defined(_LIBCPP_VERSION) { - using C = std::flat_multiset<MoveOnly, ThrowingDtorComp>; + using C = std::flat_multiset<MoveOnly, ThrowingDtorComp, KeyContainer<MoveOnly>>; static_assert(!std::is_nothrow_destructible_v<C>); C c; } #endif // _LIBCPP_VERSION } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + test<std::deque>(); + } + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/initializer_list.pass.cpp index 10638d7..36f5def 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/initializer_list.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/initializer_list.pass.cpp @@ -32,12 +32,13 @@ #include "../../../test_compare.h" struct DefaultCtableComp { - explicit DefaultCtableComp() { default_constructed_ = true; } - bool operator()(int, int) const { return false; } + constexpr explicit DefaultCtableComp() { default_constructed_ = true; } + constexpr bool operator()(int, int) const { return false; } bool default_constructed_ = false; }; -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -45,8 +46,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; using IL = std::initializer_list<int>; @@ -60,10 +61,9 @@ void test() { static_assert(!std::is_constructible_v<M1, IL, const C&, const A2&>); static_assert(!std::is_constructible_v<M2, IL, const C&, const A1&>); } - { // initializer_list<value_type> needs to match exactly - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; using C = typename M::key_compare; static_assert(std::is_constructible_v<M, std::initializer_list<int>>); static_assert(std::is_constructible_v<M, std::initializer_list<int>, C>); @@ -78,11 +78,10 @@ void test() { static_assert(!std::is_constructible_v<M, std::initializer_list<const int>, C, std::allocator<int>>); static_assert(!std::is_constructible_v<M, std::initializer_list<const int>, std::allocator<int>>); } - int expected[] = {1, 2, 2, 3, 3, 5}; { // flat_multiset(initializer_list<value_type>); - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; std::initializer_list<int> il = {5, 2, 2, 3, 1, 3}; M m(il); assert(std::ranges::equal(m, expected)); @@ -90,13 +89,13 @@ void test() { { // flat_multiset(initializer_list<value_type>); // explicit(false) - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; M m = {5, 2, 2, 3, 1, 3}; assert(std::ranges::equal(m, expected)); } { // flat_multiset(initializer_list<value_type>); - using M = std::flat_multiset<int, std::greater<int>, std::deque<int, min_allocator<int>>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, min_allocator<int>>>; M m = {5, 2, 2, 3, 1, 3}; assert(std::ranges::equal(m, expected | std::views::reverse)); } @@ -105,15 +104,14 @@ void test() { { // flat_multiset(initializer_list<value_type>); // different comparator - using M = std::flat_multiset<int, DefaultCtableComp, std::vector<int, A>>; + using M = std::flat_multiset<int, DefaultCtableComp, KeyContainer<int, A>>; M m = {1, 2, 3}; assert(m.size() == 3); - LIBCPP_ASSERT(*m.begin() == 1); assert(m.key_comp().default_constructed_); } { // flat_multiset(initializer_list<value_type>, const Allocator&); - using M = std::flat_multiset<int, std::greater<int>, std::deque<int, A>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, A>>; A a; M m({5, 2, 2, 3, 1, 3}, a); assert(std::ranges::equal(m, expected | std::views::reverse)); @@ -122,7 +120,7 @@ void test() { { // flat_multiset(initializer_list<value_type>, const key_compare&); using C = test_less<int>; - using M = std::flat_multiset<int, C>; + using M = std::flat_multiset<int, C, KeyContainer<int>>; auto m = M({5, 2, 2, 3, 1, 3}, C(10)); assert(std::ranges::equal(m, expected)); assert(m.key_comp() == C(10)); @@ -132,10 +130,10 @@ void test() { assert(m2 == m); assert(m2.key_comp() == C(10)); } - { + if (!TEST_IS_CONSTANT_EVALUATED) { // flat_multiset(initializer_list<value_type>, const key_compare&); // Sorting uses the comparator that was passed in - using M = std::flat_multiset<int, std::function<bool(int, int)>, std::deque<int, min_allocator<int>>>; + using M = std::flat_multiset<int, std::function<bool(int, int)>, KeyContainer<int, min_allocator<int>>>; auto m = M({5, 2, 2, 1, 3, 3}, std::greater<int>()); assert(std::ranges::equal(m, expected | std::views::reverse)); assert(m.key_comp()(2, 1) == true); @@ -143,15 +141,31 @@ void test() { { // flat_multiset(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); using A = explicit_allocator<int>; - using M = std::flat_multiset<int, std::greater<int>, std::deque<int, A>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, A>>; A a; M m({5, 2, 2, 3, 1, 3}, {}, a); assert(std::ranges::equal(m, expected | std::views::reverse)); } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + test<std::deque>(); + } + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/iter_iter.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/iter_iter.pass.cpp index da9aef3..0f757db 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/iter_iter.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/iter_iter.pass.cpp @@ -30,7 +30,8 @@ #include "test_macros.h" #include "../../../test_compare.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -38,8 +39,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; using Iter1 = typename M1::iterator; @@ -60,7 +61,7 @@ void test() { { // flat_multiset(InputIterator , InputIterator) // cpp17_input_iterator - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; auto m = M(cpp17_input_iterator<const int*>(ar), cpp17_input_iterator<const int*>(ar + 9)); assert(std::ranges::equal(m, expected)); @@ -71,21 +72,21 @@ void test() { { // flat_multiset(InputIterator , InputIterator) // greater - using M = std::flat_multiset<int, std::greater<int>, std::deque<int, min_allocator<int>>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, min_allocator<int>>>; auto m = M(cpp17_input_iterator<const int*>(ar), cpp17_input_iterator<const int*>(ar + 9)); assert(std::ranges::equal(m, expected | std::views::reverse)); } { // flat_multiset(InputIterator , InputIterator) // Test when the operands are of array type (also contiguous iterator type) - using M = std::flat_multiset<int, std::greater<int>, std::vector<int, min_allocator<int>>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, min_allocator<int>>>; auto m = M(ar, ar); assert(m.empty()); } { // flat_multiset(InputIterator , InputIterator, const key_compare&) using C = test_less<int>; - using M = std::flat_multiset<int, C, std::vector<int>>; + using M = std::flat_multiset<int, C, KeyContainer<int>>; auto m = M(ar, ar + 9, C(3)); assert(std::ranges::equal(m, expected)); assert(m.key_comp() == C(3)); @@ -98,7 +99,7 @@ void test() { { // flat_multiset(InputIterator , InputIterator, const Allocator&) using A1 = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::vector<int, A1>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A1>>; auto m = M(ar, ar + 9, A1(5)); assert(std::ranges::equal(m, expected)); assert(std::move(m).extract().get_allocator() == A1(5)); @@ -107,7 +108,7 @@ void test() { // flat_multiset(InputIterator , InputIterator, const Allocator&) // explicit(false) using A1 = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::vector<int, A1>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A1>>; M m = {ar, ar + 9, A1(5)}; // implicit ctor assert(std::ranges::equal(m, expected)); assert(std::move(m).extract().get_allocator() == A1(5)); @@ -116,7 +117,7 @@ void test() { // flat_multiset(InputIterator , InputIterator, const key_compare&, const Allocator&) using C = test_less<int>; using A1 = test_allocator<int>; - using M = std::flat_multiset<int, C, std::vector<int, A1>>; + using M = std::flat_multiset<int, C, KeyContainer<int, A1>>; auto m = M(ar, ar + 9, C(3), A1(5)); assert(std::ranges::equal(m, expected)); assert(m.key_comp() == C(3)); @@ -126,7 +127,7 @@ void test() { // flat_multiset(InputIterator , InputIterator, const key_compare&, const Allocator&) // explicit(false) using A1 = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::deque<int, A1>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A1>>; M m = {ar, ar + 9, {}, A1(5)}; // implicit ctor assert(std::ranges::equal(m, expected)); LIBCPP_ASSERT(std::ranges::equal(m, expected)); @@ -134,8 +135,21 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move.pass.cpp index 825ad75..7fb0c0e 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move.pass.cpp @@ -25,11 +25,12 @@ #include "test_allocator.h" #include "min_allocator.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { using C = test_less<int>; using A = test_allocator<int>; - using M = std::flat_multiset<int, C, std::deque<int, A>>; + using M = std::flat_multiset<int, C, KeyContainer<int, A>>; M mo = M({1, 2, 1, 3}, C(5), A(7)); M m = std::move(mo); assert((m == M{1, 1, 2, 3})); @@ -43,7 +44,7 @@ void test() { { using C = test_less<int>; using A = min_allocator<int>; - using M = std::flat_multiset<int, C, std::vector<int, A>>; + using M = std::flat_multiset<int, C, KeyContainer<int, A>>; M mo = M({1, 2, 1, 3}, C(5), A()); M m = std::move(mo); assert((m == M{1, 1, 2, 3})); @@ -54,9 +55,9 @@ void test() { assert(mo.key_comp() == C(5)); assert(std::move(mo).extract().get_allocator() == A()); } - { + if (!TEST_IS_CONSTANT_EVALUATED) { // A moved-from flat_multiset maintains its class invariant in the presence of moved-from comparators. - using M = std::flat_multiset<int, std::function<bool(int, int)>>; + using M = std::flat_multiset<int, std::function<bool(int, int)>, KeyContainer<int>>; M mo = M({1, 2, 1, 3}, std::less<int>()); M m = std::move(mo); assert(m.size() == 4); @@ -81,6 +82,16 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + template <class T> struct ThrowingMoveAllocator { using value_type = T; @@ -179,6 +190,9 @@ void test_move_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_move_noexcept(); #if !defined(TEST_HAS_NO_EXCEPTIONS) test_move_exception(); diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_alloc.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_alloc.pass.cpp index ee8258e..1f095ed 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_alloc.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_alloc.pass.cpp @@ -24,7 +24,8 @@ #include "../../../test_compare.h" #include "test_allocator.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -32,8 +33,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; static_assert(std::is_constructible_v<M1, M1&&, const A1&>); @@ -45,7 +46,7 @@ void test() { int expected[] = {1, 1, 2, 2, 3}; using C = test_less<int>; using A = test_allocator<int>; - using M = std::flat_multiset<int, C, std::deque<int, A>>; + using M = std::flat_multiset<int, C, KeyContainer<int, A>>; auto mo = M(expected, expected + 5, C(5), A(7)); auto m = M(std::move(mo), A(3)); @@ -72,8 +73,21 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_assign.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_assign.pass.cpp index 96e046e..62e2181 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_assign.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/move_assign.pass.cpp @@ -187,25 +187,12 @@ void test_move_assign_no_except() { } } -void test() { - { - using C = test_less<int>; - using A1 = test_allocator<int>; - using M = std::flat_multiset<int, C, std::vector<int, A1>>; - M mo = M({1, 1, 2, 3}, C(5), A1(7)); - M m = M({}, C(3), A1(7)); - std::same_as<M&> decltype(auto) r = m = std::move(mo); - assert(&r == &m); - assert((m == M{1, 1, 2, 3})); - assert(m.key_comp() == C(5)); - auto ks = std::move(m).extract(); - assert(ks.get_allocator() == A1(7)); - assert(mo.empty()); - } +template <template <class...> class KeyContainer> +constexpr void test() { { using C = test_less<int>; using A1 = other_allocator<int>; - using M = std::flat_multiset<int, C, std::deque<int, A1>>; + using M = std::flat_multiset<int, C, KeyContainer<int, A1>>; M mo = M({4, 4, 5}, C(5), A1(7)); M m = M({1, 1, 2, 3, 4}, C(3), A1(7)); std::same_as<M&> decltype(auto) r = m = std::move(mo); @@ -218,7 +205,7 @@ void test() { } { using A = min_allocator<int>; - using M = std::flat_multiset<int, std::greater<int>, std::vector<int, A>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, A>>; M mo = M({5, 3, 4, 3}, A()); M m = M({4, 1, 3, 2, 1}, A()); std::same_as<M&> decltype(auto) r = m = std::move(mo); @@ -228,10 +215,37 @@ void test() { assert(ks.get_allocator() == A()); assert(mo.empty()); } + { + using C = test_less<int>; + using A1 = test_allocator<int>; + using M = std::flat_multiset<int, C, KeyContainer<int, A1>>; + M mo = M({1, 1, 2, 3}, C(5), A1(7)); + M m = M({}, C(3), A1(7)); + std::same_as<M&> decltype(auto) r = m = std::move(mo); + assert(&r == &m); + assert((m == M{1, 1, 2, 3})); + assert(m.key_comp() == C(5)); + auto ks = std::move(m).extract(); + assert(ks.get_allocator() == A1(7)); + assert(mo.empty()); + } +} + +constexpr bool test() { + test<std::vector>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_move_assign_clears(); test_move_assign_no_except(); diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/range.pass.cpp index 76485b4..36501a5 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/range.pass.cpp @@ -56,7 +56,8 @@ static_assert( !std:: is_constructible_v<Set, std::from_range_t, RangeOf<std::pair<int, int>>, std::less<int>, std::allocator<int>>); -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -64,8 +65,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; static_assert(std::is_constructible_v<M1, std::from_range_t, M1, const A1&>); @@ -84,7 +85,7 @@ void test() { { // flat_multiset(from_range_t, R&&) // input_range && !common - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; using Iter = cpp20_input_iterator<const int*>; using Sent = sentinel_wrapper<Iter>; using R = std::ranges::subrange<Iter, Sent>; @@ -98,17 +99,17 @@ void test() { { // flat_multiset(from_range_t, R&&) // greater - using M = std::flat_multiset<int, std::greater<int>, std::deque<int, min_allocator<int>>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, min_allocator<int>>>; using Iter = cpp20_input_iterator<const int*>; using Sent = sentinel_wrapper<Iter>; using R = std::ranges::subrange<Iter, Sent>; auto m = M(std::from_range, R(Iter(ar), Sent(Iter(ar + 9)))); - assert(std::ranges::equal(m, std::deque<int, min_allocator<int>>{3, 3, 3, 2, 2, 2, 1, 1, 1})); + assert(std::ranges::equal(m, KeyContainer<int, min_allocator<int>>{3, 3, 3, 2, 2, 2, 1, 1, 1})); } { // flat_multiset(from_range_t, R&&) // contiguous range - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; using R = std::ranges::subrange<const int*>; auto m = M(std::from_range, R(ar, ar + 9)); assert(std::ranges::equal(m, expected)); @@ -116,7 +117,7 @@ void test() { { // flat_multiset(from_range_t, R&&, const key_compare&) using C = test_less<int>; - using M = std::flat_multiset<int, C, std::vector<int>>; + using M = std::flat_multiset<int, C, KeyContainer<int>>; using R = std::ranges::subrange<const int*>; auto m = M(std::from_range, R(ar, ar + 9), C(3)); assert(std::ranges::equal(m, expected)); @@ -130,7 +131,7 @@ void test() { { // flat_multiset(from_range_t, R&&, const Allocator&) using A1 = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::vector<int, A1>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A1>>; using R = std::ranges::subrange<const int*>; auto m = M(std::from_range, R(ar, ar + 9), A1(5)); assert(std::ranges::equal(m, expected)); @@ -140,7 +141,7 @@ void test() { // flat_multiset(from_range_t, R&&, const Allocator&) // explicit(false) using A1 = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::deque<int, A1>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A1>>; using R = std::ranges::subrange<const int*>; M m = {std::from_range, R(ar, ar + 9), A1(5)}; // implicit ctor assert(std::ranges::equal(m, expected)); @@ -150,7 +151,7 @@ void test() { // flat_multiset(from_range_t, R&&, const key_compare&, const Allocator&) using C = test_less<int>; using A1 = test_allocator<int>; - using M = std::flat_multiset<int, C, std::vector<int, A1>>; + using M = std::flat_multiset<int, C, KeyContainer<int, A1>>; using R = std::ranges::subrange<const int*>; auto m = M(std::from_range, R(ar, ar + 9), C(3), A1(5)); assert(std::ranges::equal(m, expected)); @@ -161,7 +162,7 @@ void test() { // flat_multiset(from_range_t, R&&, const key_compare&, const Allocator&) // explicit(false) using A1 = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::deque<int, A1>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A1>>; using R = std::ranges::subrange<const int*>; M m = {std::from_range, R(ar, ar + 9), {}, A1(5)}; // implicit ctor assert(std::ranges::equal(m, expected)); @@ -169,8 +170,21 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_container.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_container.pass.cpp index 76759be..60fd70a 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_container.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_container.pass.cpp @@ -30,7 +30,8 @@ #include "test_macros.h" #include "../../../test_compare.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -38,8 +39,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; static_assert(std::is_constructible_v<M1, std::sorted_equivalent_t, const V1&, const A1&>); @@ -52,11 +53,12 @@ void test() { static_assert(!std::is_constructible_v<M1, std::sorted_equivalent_t, const V1&, const C&, const A2&>); static_assert(!std::is_constructible_v<M2, std::sorted_equivalent_t, const V2&, const C&, const A1&>); } + { // flat_multiset(sorted_equivalent_t, container_type) - using M = std::flat_multiset<int>; - std::vector<int> ks = {1, 2, 2, 4, 10}; - auto ks2 = ks; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; + KeyContainer<int> ks = {1, 2, 2, 4, 10}; + auto ks2 = ks; auto m = M(std::sorted_equivalent, ks); assert((m == M{1, 2, 2, 4, 10})); @@ -71,7 +73,7 @@ void test() { { // flat_multiset(sorted_equivalent_t, container_type) // non-default container, comparator and allocator type - using Ks = std::deque<int, min_allocator<int>>; + using Ks = KeyContainer<int, min_allocator<int>>; using M = std::flat_multiset<int, std::greater<int>, Ks>; Ks ks = {10, 4, 4, 2, 1}; auto m = M(std::sorted_equivalent, ks); @@ -84,8 +86,8 @@ void test() { // flat_multiset(sorted_equivalent_t, container_type) // allocator copied into the containers using A = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::deque<int, A>>; - auto ks = std::deque<int, A>({1, 2, 2, 4, 10}, A(4)); + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A>>; + auto ks = KeyContainer<int, A>({1, 2, 2, 4, 10}, A(4)); auto m = M(std::sorted_equivalent, std::move(ks)); assert(ks.empty()); // it was moved-from assert((m == M{1, 2, 2, 4, 10})); @@ -93,9 +95,9 @@ void test() { } { // flat_multiset(sorted_equivalent_t, container_type , key_compare) - using C = test_less<int>; - using M = std::flat_multiset<int, C>; - std::vector<int> ks = {1, 2, 2, 4, 10}; + using C = test_less<int>; + using M = std::flat_multiset<int, C, KeyContainer<int>>; + KeyContainer<int> ks = {1, 2, 2, 4, 10}; auto m = M(std::sorted_equivalent, ks, C(4)); assert((m == M{1, 2, 2, 4, 10})); @@ -108,11 +110,11 @@ void test() { } { // flat_multiset(sorted_equivalent_t, container_type , key_compare, const Allocator&) - using C = test_less<int>; - using A = test_allocator<int>; - using M = std::flat_multiset<int, C, std::vector<int, A>>; - std::vector<int, A> ks = {1, 2, 2, 4, 10}; - auto m = M(std::sorted_equivalent, ks, C(4), A(5)); + using C = test_less<int>; + using A = test_allocator<int>; + using M = std::flat_multiset<int, C, KeyContainer<int, A>>; + KeyContainer<int, A> ks = {1, 2, 2, 4, 10}; + auto m = M(std::sorted_equivalent, ks, C(4), A(5)); assert((m == M{1, 2, 2, 4, 10})); assert(m.key_comp() == C(4)); assert(M(m).extract().get_allocator() == A(5)); @@ -126,8 +128,8 @@ void test() { { // flat_multiset(sorted_equivalent_t, container_type , const Allocator&) using A = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::deque<int, A>>; - auto ks = std::deque<int, A>({1, 2, 2, 4, 10}, A(4)); + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A>>; + auto ks = KeyContainer<int, A>({1, 2, 2, 4, 10}, A(4)); auto m = M(std::sorted_equivalent, ks, A(6)); // replaces the allocators assert(!ks.empty()); // it was an lvalue above assert((m == M{1, 2, 2, 4, 10})); @@ -140,8 +142,22 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_initializer_list.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_initializer_list.pass.cpp index 955662d..ff10c97 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_initializer_list.pass.cpp @@ -31,12 +31,13 @@ #include "../../../test_compare.h" template <class T> -std::initializer_list<T> il = {1, 2, 4, 4, 5}; +constexpr std::initializer_list<T> il = {1, 2, 4, 4, 5}; -void test() { - const auto il1 = il<int>; - const auto il2 = il<short>; +constexpr auto il1 = il<int>; +constexpr auto il2 = il<short>; +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -44,8 +45,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; using IL = std::initializer_list<int>; @@ -62,7 +63,7 @@ void test() { } { // initializer_list<value_type> needs to match exactly - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; using C = typename M::key_compare; static_assert(std::is_constructible_v<M, std::sorted_equivalent_t, std::initializer_list<int>>); static_assert(std::is_constructible_v<M, std::sorted_equivalent_t, std::initializer_list<int>, C>); @@ -88,7 +89,7 @@ void test() { { // flat_multiset(sorted_equivalent_t, initializer_list<value_type>); - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; auto m = M(std::sorted_equivalent, il1); auto expected = M{1, 2, 4, 4, 5}; assert(m == expected); @@ -97,9 +98,9 @@ void test() { M m2 = {std::sorted_equivalent, il1}; assert(m2 == m); } - { + if (!TEST_IS_CONSTANT_EVALUATED) { // flat_multiset(sorted_equivalent_t, initializer_list<value_type>, const key_compare&); - using M = std::flat_multiset<int, std::function<bool(int, int)>>; + using M = std::flat_multiset<int, std::function<bool(int, int)>, KeyContainer<int>>; auto m = M(std::sorted_equivalent, il1, std::less<int>()); assert(m == M({1, 2, 4, 4, 5}, std::less<>())); assert(m.key_comp()(1, 2) == true); @@ -111,7 +112,7 @@ void test() { { // flat_multiset(sorted_equivalent_t, initializer_list<value_type>, const key_compare&); // greater - using M = std::flat_multiset<int, std::greater<int>, std::deque<int, min_allocator<int>>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, min_allocator<int>>>; std::initializer_list<int> il4{5, 4, 4, 2, 1}; auto m = M(std::sorted_equivalent, il4, std::greater<int>()); assert((m == M{5, 4, 4, 2, 1})); @@ -119,7 +120,7 @@ void test() { { // flat_multiset(sorted_equivalent_t, initializer_list<value_type>, const Allocator&) using A1 = test_allocator<short>; - using M = std::flat_multiset<short, std::less<int>, std::deque<short, A1>>; + using M = std::flat_multiset<short, std::less<int>, KeyContainer<short, A1>>; auto m = M(std::sorted_equivalent, il2, A1(5)); auto expected = M{1, 2, 4, 4, 5}; assert(m == expected); @@ -134,7 +135,7 @@ void test() { // flat_multiset(sorted_equivalent_t, initializer_list<value_type>, const key_compare&, const Allocator&); using C = test_less<int>; using A1 = test_allocator<short>; - using M = std::flat_multiset<short, C, std::vector<short, A1>>; + using M = std::flat_multiset<short, C, KeyContainer<short, A1>>; auto m = M(std::sorted_equivalent, il2, C(3), A1(5)); assert((m == M{1, 2, 4, 4, 5})); assert(m.key_comp() == C(3)); @@ -144,15 +145,29 @@ void test() { // flat_multiset(sorted_equivalent_t, initializer_list<value_type>, const key_compare&, const Allocator&); // explicit(false) using A1 = test_allocator<short>; - using M = std::flat_multiset<short, std::less<int>, std::deque<short, A1>>; + using M = std::flat_multiset<short, std::less<int>, KeyContainer<short, A1>>; M m = {std::sorted_equivalent, il2, {}, A1(5)}; // implicit ctor assert((m == M{1, 2, 4, 4, 5})); assert(std::move(m).extract().get_allocator() == A1(5)); } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_iter_iter.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_iter_iter.pass.cpp index 9ebe45d..a3c9981 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/sorted_iter_iter.pass.cpp @@ -28,7 +28,8 @@ #include "test_macros.h" #include "../../../test_compare.h" -void test() { +template <template <class...> class KeyContainer> +constexpr void test() { { // The constructors in this subclause shall not participate in overload // resolution unless uses_allocator_v<container_type, Alloc> is true. @@ -36,8 +37,8 @@ void test() { using C = test_less<int>; using A1 = test_allocator<int>; using A2 = other_allocator<int>; - using V1 = std::vector<int, A1>; - using V2 = std::vector<int, A2>; + using V1 = KeyContainer<int, A1>; + using V2 = KeyContainer<int, A2>; using M1 = std::flat_multiset<int, C, V1>; using M2 = std::flat_multiset<int, C, V2>; using Iter1 = typename M1::iterator; @@ -52,10 +53,12 @@ void test() { static_assert(!std::is_constructible_v<M1, std::sorted_equivalent_t, Iter1, Iter1, const C&, const A2&>); static_assert(!std::is_constructible_v<M2, std::sorted_equivalent_t, Iter2, Iter2, const C&, const A1&>); } + { // flat_multiset(sorted_equivalent_t, InputIterator, InputIterator); // cpp17_input_iterator - using M = std::flat_multiset<int>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int>>; + int ar[] = {1, 2, 2, 4, 5}; auto m = M(std::sorted_equivalent, cpp17_input_iterator<const int*>(ar), cpp17_input_iterator<const int*>(ar + 5)); auto expected = M{1, 2, 2, 4, 5}; @@ -69,16 +72,16 @@ void test() { // flat_multiset(sorted_equivalent_t, InputIterator, InputIterator); // contiguous iterator using C = test_less<int>; - using M = std::flat_multiset<int, C, std::vector<int, min_allocator<int>>>; + using M = std::flat_multiset<int, C, KeyContainer<int, min_allocator<int>>>; int ar[] = {1, 2, 4, 4, 5}; auto m = M(std::sorted_equivalent, ar, ar + 5); auto expected = M{1, 2, 4, 4, 5}; assert(m == expected); } - { + if (!TEST_IS_CONSTANT_EVALUATED) { // flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, const key_compare&); // cpp_17_input_iterator - using M = std::flat_multiset<int, std::function<bool(int, int)>>; + using M = std::flat_multiset<int, std::function<bool(int, int)>, KeyContainer<int>>; int ar[] = {1, 2, 4, 4, 5}; auto m = M(std::sorted_equivalent, cpp17_input_iterator<const int*>(ar), @@ -97,7 +100,7 @@ void test() { { // flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, const key_compare&); // greater - using M = std::flat_multiset<int, std::greater<int>, std::deque<int, min_allocator<int>>>; + using M = std::flat_multiset<int, std::greater<int>, KeyContainer<int, min_allocator<int>>>; int ar[] = {5, 4, 4, 2, 1}; auto m = M(std::sorted_equivalent, cpp17_input_iterator<const int*>(ar), @@ -109,7 +112,7 @@ void test() { // flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, const key_compare&); // contiguous iterator using C = test_less<int>; - using M = std::flat_multiset<int, C, std::vector<int, min_allocator<int>>>; + using M = std::flat_multiset<int, C, KeyContainer<int, min_allocator<int>>>; int ar[1] = {42}; auto m = M(std::sorted_equivalent, ar, ar, C(5)); assert(m.empty()); @@ -118,7 +121,7 @@ void test() { { // flat_multiset(sorted_equivalent_t, InputIterator , InputIterator, const Allocator&) using A1 = test_allocator<int>; - using M = std::flat_multiset<int, std::less<int>, std::vector<int, A1>>; + using M = std::flat_multiset<int, std::less<int>, KeyContainer<int, A1>>; int ar[] = {1, 2, 4, 4, 5}; auto m = M(std::sorted_equivalent, ar, ar + 5, A1(5)); auto expected = M{1, 2, 4, 4, 5}; @@ -134,7 +137,7 @@ void test() { // flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, const key_compare&, const Allocator&); using C = test_less<int>; using A1 = test_allocator<int>; - using M = std::flat_multiset<int, C, std::deque<int, A1>>; + using M = std::flat_multiset<int, C, KeyContainer<int, A1>>; int ar[] = {1, 2, 4, 4, 5}; auto m = M(std::sorted_equivalent, ar, ar + 5, C(3), A1(5)); assert((m == M{1, 2, 4, 4, 5})); @@ -145,7 +148,7 @@ void test() { // flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, const key_compare&, const Allocator&); // explicit(false) using A1 = test_allocator<short>; - using M = std::flat_multiset<short, std::less<int>, std::deque<short, A1>>; + using M = std::flat_multiset<short, std::less<int>, KeyContainer<short, A1>>; int ar[] = {1, 2, 4, 4, 5}; M m = {std::sorted_equivalent, ar, ar + 5, {}, A1(5)}; // implicit ctor assert((m == M{1, 2, 4, 4, 5})); @@ -153,8 +156,22 @@ void test() { } } +constexpr bool test() { + test<std::vector>(); + +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test<std::deque>(); + + return true; +} + int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.erasure/erase_if.pass.cpp index 21f3c91..337ad04 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.erasure/erase_if.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.erasure/erase_if.pass.cpp @@ -32,7 +32,7 @@ static_assert(HasStdErase<std::vector<int>>); static_assert(!HasStdErase<std::flat_multiset<int>>); template <class M> -M make(std::initializer_list<int> vals) { +constexpr M make(std::initializer_list<int> vals) { M ret; for (int v : vals) ret.emplace(v); @@ -40,8 +40,8 @@ M make(std::initializer_list<int> vals) { } template <class M, class Pred> -void test0( - std::initializer_list<int> vals, Pred p, std::initializer_list<int> expected, std::size_t expected_erased_count) { +constexpr void +test0(std::initializer_list<int> vals, Pred p, std::initializer_list<int> expected, std::size_t expected_erased_count) { M s = make<M>(vals); ASSERT_SAME_TYPE(typename M::size_type, decltype(std::erase_if(s, p))); assert(expected_erased_count == std::erase_if(s, p)); @@ -50,11 +50,11 @@ void test0( struct NotBool { bool b; - explicit operator bool() const { return b; } + explicit constexpr operator bool() const { return b; } }; template <class S> -void test_one() { +constexpr void test_one() { // Test all the plausible signatures for this predicate. auto is1 = [](typename S::const_reference v) { return v == 1; }; auto is2 = [](typename S::value_type v) { return v == 2; }; @@ -96,18 +96,28 @@ void test_one() { test0<S>({1, 1, 2, 2, 3}, nonBoolIs1, {2, 2, 3}, 2); } -void test() { +constexpr bool test() { test_one<std::flat_multiset<int>>(); test_one<std::flat_multiset<int, std::less<int>, std::vector<int, min_allocator<int>>>>(); test_one<std::flat_multiset<int, std::greater<int>, std::vector<int, test_allocator<int>>>>(); - test_one<std::flat_multiset<int, std::less<int>, std::deque<int, min_allocator<int>>>>(); - test_one<std::flat_multiset<int, std::greater<int>, std::deque<int, test_allocator<int>>>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + test_one<std::flat_multiset<int, std::less<int>, std::deque<int, min_allocator<int>>>>(); + test_one<std::flat_multiset<int, std::greater<int>, std::deque<int, test_allocator<int>>>>(); + } test_one<std::flat_multiset<long>>(); test_one<std::flat_multiset<double>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator.pass.cpp index 809f03d..878b2b2 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator.pass.cpp @@ -30,7 +30,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; @@ -68,9 +68,12 @@ void test_one() { assert(i == m.begin()); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); @@ -89,10 +92,15 @@ void test() { assert(!(ii1 != cii)); assert(!(cii != ii1)); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp index cbf69d6..ff4ad3f 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp @@ -24,7 +24,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using I = M::iterator; @@ -141,15 +141,23 @@ void test_one() { assert(cri2 <=> cri1 == std::strong_ordering::greater); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/reverse_iterator.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/reverse_iterator.pass.cpp index e25d786..678109b 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/reverse_iterator.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/reverse_iterator.pass.cpp @@ -25,46 +25,59 @@ #include <iterator> +#include "MinSequenceContainer.h" #include "test_macros.h" +#include "min_allocator.h" -void test() { - { - using M = std::flat_multiset<int, std::less<int>, std::deque<int>>; - M m = {1, 1, 2, 2, 3, 4}; - int expected[] = {1, 1, 2, 2, 3, 4}; - const M& cm = m; - ASSERT_SAME_TYPE(decltype(m.rbegin()), M::reverse_iterator); - ASSERT_SAME_TYPE(decltype(m.crbegin()), M::const_reverse_iterator); - ASSERT_SAME_TYPE(decltype(cm.rbegin()), M::const_reverse_iterator); - ASSERT_SAME_TYPE(decltype(m.rend()), M::reverse_iterator); - ASSERT_SAME_TYPE(decltype(m.crend()), M::const_reverse_iterator); - ASSERT_SAME_TYPE(decltype(cm.rend()), M::const_reverse_iterator); - static_assert(noexcept(m.rbegin())); - static_assert(noexcept(cm.rbegin())); - static_assert(noexcept(m.crbegin())); - static_assert(noexcept(m.rend())); - static_assert(noexcept(cm.rend())); - static_assert(noexcept(m.crend())); - assert(m.size() == 6); - assert(std::distance(m.rbegin(), m.rend()) == 6); - assert(std::distance(cm.rbegin(), cm.rend()) == 6); - assert(std::distance(m.crbegin(), m.crend()) == 6); - assert(std::distance(cm.crbegin(), cm.crend()) == 6); - M::reverse_iterator i; // default-construct - ASSERT_SAME_TYPE(decltype(*i), const int&); - i = m.rbegin(); // move-assignment - M::const_reverse_iterator k = i; // converting constructor - assert(i == k); // comparison - for (int j = 5; j >= 0; --j, ++i) { // pre-increment - assert(*i == expected[j]); - } - assert(i == m.rend()); - for (int j = 0; j <= 5; ++j) { - --i; // pre-decrement - assert(*i == expected[j]); - } - assert(i == m.rbegin()); +template <class KeyContainer> +constexpr void test_one() { + using Key = typename KeyContainer::value_type; + using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; + M m = {1, 1, 2, 2, 3, 4}; + int expected[] = {1, 1, 2, 2, 3, 4}; + const M& cm = m; + ASSERT_SAME_TYPE(decltype(m.rbegin()), typename M::reverse_iterator); + ASSERT_SAME_TYPE(decltype(m.crbegin()), typename M::const_reverse_iterator); + ASSERT_SAME_TYPE(decltype(cm.rbegin()), typename M::const_reverse_iterator); + ASSERT_SAME_TYPE(decltype(m.rend()), typename M::reverse_iterator); + ASSERT_SAME_TYPE(decltype(m.crend()), typename M::const_reverse_iterator); + ASSERT_SAME_TYPE(decltype(cm.rend()), typename M::const_reverse_iterator); + static_assert(noexcept(m.rbegin())); + static_assert(noexcept(cm.rbegin())); + static_assert(noexcept(m.crbegin())); + static_assert(noexcept(m.rend())); + static_assert(noexcept(cm.rend())); + static_assert(noexcept(m.crend())); + assert(m.size() == 6); + assert(std::distance(m.rbegin(), m.rend()) == 6); + assert(std::distance(cm.rbegin(), cm.rend()) == 6); + assert(std::distance(m.crbegin(), m.crend()) == 6); + assert(std::distance(cm.crbegin(), cm.crend()) == 6); + typename M::reverse_iterator i; // default-construct + ASSERT_SAME_TYPE(decltype(*i), const int&); + i = m.rbegin(); // move-assignment + typename M::const_reverse_iterator k = i; // converting constructor + assert(i == k); // comparison + for (int j = 5; j >= 0; --j, ++i) { // pre-increment + assert(*i == expected[j]); + } + assert(i == m.rend()); + for (int j = 0; j <= 5; ++j) { + --i; // pre-decrement + assert(*i == expected[j]); } + assert(i == m.rbegin()); +} + +constexpr bool test() { + test_one<std::vector<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); + test_one<MinSequenceContainer<int>>(); + test_one<std::vector<int, min_allocator<int>>>(); + { // N3644 testing using C = std::flat_multiset<int>; @@ -80,10 +93,15 @@ void test() { assert(!(ii1 != cii)); assert(!(cii != ii1)); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/clear.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/clear.pass.cpp index 4d01ece7..088a883 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/clear.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/clear.pass.cpp @@ -38,7 +38,7 @@ static_assert(NoExceptClear<std::flat_multiset<int, std::less<int>, ThrowOnMoveC #endif template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; { @@ -58,17 +58,25 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace.pass.cpp index 3ef1396..6772e17 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace.pass.cpp @@ -28,7 +28,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using R = typename M::iterator; @@ -91,7 +91,7 @@ void test_one() { } template <class KeyContainer> -void test_emplaceable() { +constexpr void test_emplaceable() { using M = std::flat_multiset<Emplaceable, std::less<Emplaceable>, KeyContainer>; using R = typename M::iterator; @@ -111,16 +111,24 @@ void test_emplaceable() { assert(*r == Emplaceable(1, 3.5)); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); test_emplaceable<std::vector<Emplaceable>>(); - test_emplaceable<std::deque<Emplaceable>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_emplaceable<std::deque<Emplaceable>>(); test_emplaceable<MinSequenceContainer<Emplaceable>>(); test_emplaceable<std::vector<Emplaceable, min_allocator<Emplaceable>>>(); + + return true; } void test_exception() { @@ -130,6 +138,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace_hint.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace_hint.pass.cpp index 41a2e9c..ec99a9f 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace_hint.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/emplace_hint.pass.cpp @@ -27,11 +27,11 @@ #include "../helpers.h" struct CompareTensDigit { - bool operator()(auto lhs, auto rhs) const { return (lhs / 10) < (rhs / 10); } + constexpr bool operator()(auto lhs, auto rhs) const { return (lhs / 10) < (rhs / 10); } }; template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using R = M::iterator; @@ -179,7 +179,6 @@ void test_one() { assert(r == m.begin() + 2); assert(m.size() == 7); assert(*r == 23); - assert(*std::next(r) == 20); } { // hint incorrect and after the last duplicate @@ -196,7 +195,7 @@ void test_one() { } template <class KeyContainer> -void test_emplaceable() { +constexpr void test_emplaceable() { using M = std::flat_multiset<Emplaceable, std::less<Emplaceable>, KeyContainer>; using R = M::iterator; @@ -216,9 +215,12 @@ void test_emplaceable() { assert(*r == Emplaceable(1, 3.5)); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); @@ -226,6 +228,8 @@ void test() { test_emplaceable<std::vector<Emplaceable>>(); test_emplaceable<MinSequenceContainer<Emplaceable>>(); test_emplaceable<std::vector<Emplaceable, min_allocator<Emplaceable>>>(); + + return true; } void test_exception() { @@ -235,6 +239,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter.pass.cpp index 8418efa..f2cb151d 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter.pass.cpp @@ -27,7 +27,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using I = M::iterator; @@ -94,11 +94,16 @@ void test_one() { assert(i8 == m.end()); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -108,6 +113,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter_iter.pass.cpp index 2d54fef..7607892 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_iter_iter.pass.cpp @@ -26,7 +26,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using I = M::iterator; @@ -78,11 +78,16 @@ void test_one() { assert(i5 == m.end()); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -92,6 +97,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key.pass.cpp index 8175afa..7ddd3d8 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key.pass.cpp @@ -26,7 +26,7 @@ #include "min_allocator.h" template <class KeyContainer, class Compare = std::less<>> -void test_one() { +constexpr void test_one() { using M = std::flat_multiset<int, Compare, KeyContainer>; auto make = [](std::initializer_list<int> il) { @@ -74,12 +74,17 @@ void test_one() { assert(m.empty()); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); test_one<std::vector<int>, std::greater<>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -94,6 +99,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key_transparent.pass.cpp index a876549..0613744 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key_transparent.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/erase_key_transparent.pass.cpp @@ -38,10 +38,10 @@ static_assert(!CanErase<const NonTransparentSet>); template <class Key, class It> struct HeterogeneousKey { - explicit HeterogeneousKey(Key key, It it) : key_(key), it_(it) {} - operator It() && { return it_; } - auto operator<=>(Key key) const { return key_ <=> key; } - friend bool operator<(const HeterogeneousKey&, const HeterogeneousKey&) { + constexpr explicit HeterogeneousKey(Key key, It it) : key_(key), it_(it) {} + constexpr operator It() && { return it_; } + constexpr auto operator<=>(Key key) const { return key_ <=> key; } + constexpr friend bool operator<(const HeterogeneousKey&, const HeterogeneousKey&) { assert(false); return false; } @@ -50,7 +50,7 @@ struct HeterogeneousKey { }; template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; @@ -70,7 +70,7 @@ void test_one() { } template <class KeyContainer> -void test_transparent_comparator() { +constexpr void test_transparent_comparator() { using M = std::flat_multiset<std::string, TransparentComparator, KeyContainer>; { M m = {"alpha", "beta", "beta", "epsilon", "epsilon", "epsilon", "eta", "eta", "gamma"}; @@ -95,14 +95,20 @@ void test_transparent_comparator() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); test_transparent_comparator<std::vector<std::string>>(); - test_transparent_comparator<std::deque<std::string>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_transparent_comparator<std::deque<std::string>>(); test_transparent_comparator<MinSequenceContainer<std::string>>(); test_transparent_comparator<std::vector<std::string, min_allocator<std::string>>>(); @@ -146,6 +152,8 @@ void test() { assert(n == 2); assert((m == M{"alpha", "epsilon", "eta", "gamma"})); } + + return true; } void test_exception() { @@ -159,6 +167,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/extract.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/extract.pass.cpp index 8a66431..bb41ced 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/extract.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/extract.pass.cpp @@ -33,7 +33,7 @@ static_assert(!CanExtract<std::flat_multiset<int> const&>); static_assert(!CanExtract<std::flat_multiset<int> const&&>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using M = std::flat_multiset<int, std::less<int>, KeyContainer>; { M m = M({1, 1, 3}); @@ -55,9 +55,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); @@ -70,6 +73,8 @@ void test() { check_invariant(m); LIBCPP_ASSERT(m.empty()); } + + return true; } void test_exception() { @@ -96,6 +101,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_cv.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_cv.pass.cpp index eeb1bdd..5128a40 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_cv.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_cv.pass.cpp @@ -23,7 +23,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using R = typename M::iterator; @@ -61,11 +61,16 @@ void test_one() { assert(*r == 1); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -79,6 +84,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_initializer_list.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_initializer_list.pass.cpp index 9c56d3b..f0b1eaf 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_initializer_list.pass.cpp @@ -23,7 +23,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; @@ -65,11 +65,16 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -84,6 +89,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_cv.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_cv.pass.cpp index 61f00f5..55a77d5 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_cv.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_cv.pass.cpp @@ -23,7 +23,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using R = typename M::iterator; @@ -61,11 +61,16 @@ void test_one() { assert(*r == 1); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -80,6 +85,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_iter.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_iter.pass.cpp index 9381568..9b10bf3 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_iter.pass.cpp @@ -37,7 +37,7 @@ static_assert(!CanInsert<Set, int, int>); static_assert(!CanInsert<Set, cpp20_input_iterator<int*>, cpp20_input_iterator<int*>>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using M = std::flat_multiset<int, std::less<int>, KeyContainer>; int ar1[] = { @@ -75,9 +75,12 @@ void test_one() { assert(m == expected2); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); { @@ -86,6 +89,8 @@ void test() { m.insert(v.begin(), v.end()); assert(std::ranges::equal(m, std::vector<int>{1, 2, 3, 4})); } + + return true; } void test_exception() { @@ -95,6 +100,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_rv.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_rv.pass.cpp index 9976c04c..8bbc6c8 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_rv.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_iter_rv.pass.cpp @@ -22,7 +22,7 @@ #include "test_macros.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; using V = Key; @@ -59,15 +59,22 @@ void test_one() { assert(*r == V(1)); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); test_one<std::vector<MoveOnly>>(); - test_one<std::deque<int>>(); - test_one<std::deque<MoveOnly>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + test_one<std::deque<int>>(); + test_one<std::deque<MoveOnly>>(); + } test_one<MinSequenceContainer<int>>(); test_one<MinSequenceContainer<MoveOnly>>(); test_one<std::vector<int, min_allocator<int>>>(); test_one<std::vector<MoveOnly, min_allocator<MoveOnly>>>(); + + return true; } void test_exception() { @@ -82,6 +89,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp index 566be39..a9d8f7e 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp @@ -39,7 +39,7 @@ static_assert(!CanInsertRange<Set, std::ranges::subrange<std::pair<int, int>*>>) static_assert(!CanInsertRange<Set, std::ranges::subrange<std::pair<short, short>*>>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; { @@ -72,9 +72,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); { @@ -85,6 +88,8 @@ void test() { MoveOnly expected[] = {1, 1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } + + return true; } void test_exception() { @@ -94,6 +99,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_rv.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_rv.pass.cpp index 9328c42..67f3036 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_rv.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_rv.pass.cpp @@ -25,7 +25,7 @@ #include "../helpers.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, TransparentComparator, KeyContainer>; using R = typename M::iterator; @@ -63,15 +63,22 @@ void test_one() { assert(*r == V(1)); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); test_one<std::vector<MoveOnly>>(); - test_one<std::deque<int>>(); - test_one<std::deque<MoveOnly>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + test_one<std::deque<int>>(); + test_one<std::deque<MoveOnly>>(); + } test_one<MinSequenceContainer<int>>(); test_one<MinSequenceContainer<MoveOnly>>(); test_one<std::vector<int, min_allocator<int>>>(); test_one<std::vector<MoveOnly, min_allocator<MoveOnly>>>(); + + return true; } void test_exception() { @@ -86,6 +93,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_initializer_list.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_initializer_list.pass.cpp index 11af199..81b7e4e 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_initializer_list.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_initializer_list.pass.cpp @@ -23,7 +23,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; { @@ -42,11 +42,16 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -61,6 +66,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_iter_iter.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_iter_iter.pass.cpp index 07b62d0..bfb2307 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_sorted_iter_iter.pass.cpp @@ -36,7 +36,7 @@ static_assert(!CanInsert<Set, std::sorted_equivalent_t, int, int>); static_assert(!CanInsert<Set, std::sorted_equivalent_t, cpp20_input_iterator<int*>, cpp20_input_iterator<int*>>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; @@ -60,11 +60,16 @@ void test_one() { assert(m == expected2); } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -76,6 +81,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/replace.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/replace.pass.cpp index 5fe6138..3c74cf6 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/replace.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/replace.pass.cpp @@ -31,7 +31,7 @@ static_assert(CanReplace<Set, std::vector<int>>); static_assert(!CanReplace<Set, const std::vector<int>&>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; { @@ -53,11 +53,16 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } void test_exception() { @@ -82,6 +87,9 @@ void test_exception() { int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif test_exception(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_free.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_free.pass.cpp index 2e3ed02..241f2cf 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_free.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_free.pass.cpp @@ -38,7 +38,7 @@ static_assert(NoExceptAdlSwap<std::flat_multiset<int, std::less<int>, ThrowOnMov #endif template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; @@ -84,15 +84,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_member.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_member.pass.cpp index 1d0d915..7ad96ed 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_member.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/swap_member.pass.cpp @@ -37,7 +37,7 @@ static_assert(NoExceptMemberSwap<std::flat_multiset<int, std::less<int>, ThrowOn #endif template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>; { @@ -82,15 +82,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.observers/comp.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.observers/comp.pass.cpp index 4ca6451..74c92f3 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.observers/comp.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.observers/comp.pass.cpp @@ -21,7 +21,7 @@ #include "test_macros.h" -void test() { +constexpr bool test() { { using M = std::flat_multiset<int>; using Comp = std::less<int>; // the default @@ -36,7 +36,7 @@ void test() { assert(vc(1, 2)); assert(!vc(2, 1)); } - { + if (!TEST_IS_CONSTANT_EVALUATED) { using Comp = std::function<bool(int, int)>; using M = std::flat_multiset<int, Comp>; Comp comp = std::greater<int>(); @@ -67,10 +67,15 @@ void test() { assert(vc(1, 2)); assert(!vc(2, 1)); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains.pass.cpp index 00fda6c..a178dfd 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains.pass.cpp @@ -23,7 +23,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; { using M = std::flat_multiset<Key, std::less<>, KeyContainer>; @@ -66,15 +66,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains_transparent.pass.cpp index abee2b1..3222762 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains_transparent.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/contains_transparent.pass.cpp @@ -35,7 +35,7 @@ static_assert(!CanContains<NonTransparentSet>); static_assert(!CanContains<const NonTransparentSet>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, TransparentComparator, KeyContainer>; @@ -60,9 +60,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<std::string>>(); - test_one<std::deque<std::string>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<std::string>>(); test_one<MinSequenceContainer<std::string>>(); test_one<std::vector<std::string, min_allocator<std::string>>>(); @@ -82,10 +85,15 @@ void test() { assert(m.contains("beta")); assert(!m.contains("charlie")); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count.pass.cpp index 1752dab..8b034df 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count.pass.cpp @@ -23,7 +23,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using S = typename KeyContainer::size_type; @@ -66,15 +66,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count_transparent.pass.cpp index a9160ae..a1a0d6b 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count_transparent.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/count_transparent.pass.cpp @@ -35,7 +35,7 @@ static_assert(!CanCount<NonTransparentSet>); static_assert(!CanCount<const NonTransparentSet>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, TransparentComparator, KeyContainer>; { @@ -59,9 +59,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<std::string>>(); - test_one<std::deque<std::string>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<std::string>>(); test_one<MinSequenceContainer<std::string>>(); test_one<std::vector<std::string, min_allocator<std::string>>>(); @@ -81,10 +84,15 @@ void test() { auto n = m.count("beta"); assert(n == 2); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range.pass.cpp index 54ae27e9..b105d19 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range.pass.cpp @@ -24,7 +24,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; { using M = std::flat_multiset<Key, std::less<>, KeyContainer>; @@ -74,15 +74,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range_transparent.pass.cpp index ae16ec1..65bff7a 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range_transparent.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/equal_range_transparent.pass.cpp @@ -36,7 +36,7 @@ static_assert(!CanEqualRange<NonTransparentSet>); static_assert(!CanEqualRange<const NonTransparentSet>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, TransparentComparator, KeyContainer>; @@ -90,9 +90,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<std::string>>(); - test_one<std::deque<std::string>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<std::string>>(); test_one<MinSequenceContainer<std::string>>(); test_one<std::vector<std::string, min_allocator<std::string>>>(); @@ -113,10 +116,15 @@ void test() { assert(first == m.begin() + 1); assert(last == m.begin() + 3); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find.pass.cpp index 49386a6..bc9a439 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find.pass.cpp @@ -25,7 +25,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, std::less<>, KeyContainer>; { @@ -50,15 +50,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find_transparent.pass.cpp index 9d0b75c..4c9c403 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find_transparent.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/find_transparent.pass.cpp @@ -36,7 +36,7 @@ static_assert(!CanFind<NonTransparentSet>); static_assert(!CanFind<const NonTransparentSet>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, TransparentComparator, KeyContainer>; @@ -77,9 +77,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<std::string>>(); - test_one<std::deque<std::string>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<std::string>>(); test_one<MinSequenceContainer<std::string>>(); test_one<std::vector<std::string, min_allocator<std::string>>>(); @@ -101,10 +104,15 @@ void test() { auto it2 = m.find("charlie"); assert(it2 == m.end()); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound.pass.cpp index ba41b82..07f0533 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound.pass.cpp @@ -24,7 +24,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; { using M = std::flat_multiset<Key, std::less<>, KeyContainer>; @@ -66,15 +66,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound_transparent.pass.cpp index c03fb27..e674c85 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound_transparent.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/lower_bound_transparent.pass.cpp @@ -36,7 +36,7 @@ static_assert(!CanLowerBound<NonTransparentSet>); static_assert(!CanLowerBound<const NonTransparentSet>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, TransparentComparator, KeyContainer>; @@ -83,9 +83,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<std::string>>(); - test_one<std::deque<std::string>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<std::string>>(); test_one<MinSequenceContainer<std::string>>(); test_one<std::vector<std::string, min_allocator<std::string>>>(); @@ -107,10 +110,15 @@ void test() { auto it2 = m.lower_bound("charlie"); assert(it2 == m.begin() + 3); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound.pass.cpp index 7828f05..d4d1992 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound.pass.cpp @@ -24,7 +24,7 @@ #include "min_allocator.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; { using M = std::flat_multiset<Key, std::less<>, KeyContainer>; @@ -67,15 +67,23 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound_transparent.pass.cpp index de517fd..75140a7 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound_transparent.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.operations/upper_bound_transparent.pass.cpp @@ -36,7 +36,7 @@ static_assert(!CanUpperBound<NonTransparentSet>); static_assert(!CanUpperBound<const NonTransparentSet>); template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; using M = std::flat_multiset<Key, TransparentComparator, KeyContainer>; @@ -83,9 +83,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<std::string>>(); - test_one<std::deque<std::string>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<std::string>>(); test_one<MinSequenceContainer<std::string>>(); test_one<std::vector<std::string, min_allocator<std::string>>>(); @@ -105,10 +108,15 @@ void test() { auto it = m.upper_bound("beta"); assert(it == m.begin() + 3); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/helpers.h b/libcxx/test/std/containers/container.adaptors/flat.multiset/helpers.h index e7ed8a0..82f91775 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/helpers.h +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/helpers.h @@ -20,7 +20,7 @@ #include "test_macros.h" template <class... Args> -void check_invariant(const std::flat_multiset<Args...>& m) { +constexpr void check_invariant(const std::flat_multiset<Args...>& m) { assert(std::is_sorted(m.begin(), m.end(), m.key_comp())); } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/op_compare.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/op_compare.pass.cpp index 94f0f2b3..606cdfc 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/op_compare.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/op_compare.pass.cpp @@ -31,7 +31,7 @@ #include "test_container_comparisons.h" template <class KeyContainer> -void test_one() { +constexpr void test_one() { using Key = typename KeyContainer::value_type; { @@ -64,9 +64,12 @@ void test_one() { } } -void test() { +constexpr bool test() { test_one<std::vector<int>>(); - test_one<std::deque<int>>(); +#ifndef __cpp_lib_constexpr_deque + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + test_one<std::deque<int>>(); test_one<MinSequenceContainer<int>>(); test_one<std::vector<int, min_allocator<int>>>(); @@ -81,7 +84,7 @@ void test() { { // Comparisons use value_type's native operators, not the comparator struct StrongComp { - bool operator()(double a, double b) const { return std::strong_order(a, b) < 0; } + constexpr bool operator()(double a, double b) const { return std::strong_order(a, b) < 0; } }; using C = std::flat_multiset<double, StrongComp>; C s1 = {1}; @@ -96,10 +99,15 @@ void test() { assert(s1 != s2); assert((s1 <=> s2) == std::partial_ordering::unordered); } + + return true; } int main(int, char**) { test(); +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp index 665a1a8..a238b75 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp @@ -17,10 +17,10 @@ // LWG 198 was superseded by LWG 2360 // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2360 - +#include <cassert> #include <iterator> #include <list> -#include <cassert> +#include <type_traits> #include "test_macros.h" diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/flat_map.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/flat_map.version.compile.pass.cpp index 9c06eee..26c8e1bc 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/flat_map.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/flat_map.version.compile.pass.cpp @@ -20,30 +20,50 @@ #if TEST_STD_VER < 14 +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_map # error "__cpp_lib_flat_map should not be defined before c++23" # endif #elif TEST_STD_VER == 14 +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_map # error "__cpp_lib_flat_map should not be defined before c++23" # endif #elif TEST_STD_VER == 17 +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_map # error "__cpp_lib_flat_map should not be defined before c++23" # endif #elif TEST_STD_VER == 20 +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_map # error "__cpp_lib_flat_map should not be defined before c++23" # endif #elif TEST_STD_VER == 23 +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + # ifndef __cpp_lib_flat_map # error "__cpp_lib_flat_map should be defined in c++23" # endif @@ -53,6 +73,13 @@ #elif TEST_STD_VER > 23 +# ifndef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should be defined in c++26" +# endif +# if __cpp_lib_constexpr_flat_map != 202502L +# error "__cpp_lib_constexpr_flat_map should have the value 202502L in c++26" +# endif + # ifndef __cpp_lib_flat_map # error "__cpp_lib_flat_map should be defined in c++26" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/flat_set.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/flat_set.version.compile.pass.cpp index 5985bdc..b29da9f 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/flat_set.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/flat_set.version.compile.pass.cpp @@ -20,30 +20,50 @@ #if TEST_STD_VER < 14 +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_set # error "__cpp_lib_flat_set should not be defined before c++23" # endif #elif TEST_STD_VER == 14 +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_set # error "__cpp_lib_flat_set should not be defined before c++23" # endif #elif TEST_STD_VER == 17 +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_set # error "__cpp_lib_flat_set should not be defined before c++23" # endif #elif TEST_STD_VER == 20 +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_flat_set # error "__cpp_lib_flat_set should not be defined before c++23" # endif #elif TEST_STD_VER == 23 +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifndef __cpp_lib_flat_set # error "__cpp_lib_flat_set should be defined in c++23" # endif @@ -53,6 +73,13 @@ #elif TEST_STD_VER > 23 +# ifndef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should be defined in c++26" +# endif +# if __cpp_lib_constexpr_flat_set != 202502L +# error "__cpp_lib_constexpr_flat_set should have the value 202502L in c++26" +# endif + # ifndef __cpp_lib_flat_set # error "__cpp_lib_flat_set should be defined in c++26" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp index 0074f3b..cb5c008 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp @@ -918,7 +918,7 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if __has_builtin(__builtin_is_within_lifetime) # ifndef __cpp_lib_is_within_lifetime # error "__cpp_lib_is_within_lifetime should be defined in c++26" # endif @@ -927,7 +927,7 @@ # endif # else # ifdef __cpp_lib_is_within_lifetime -# error "__cpp_lib_is_within_lifetime should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_is_within_lifetime should not be defined when the requirement '__has_builtin(__builtin_is_within_lifetime)' is not met!" # endif # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index 05af1fb..8189c5c 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -204,6 +204,14 @@ # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_forward_list # error "__cpp_lib_constexpr_forward_list should not be defined before c++26" # endif @@ -1116,6 +1124,14 @@ # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_forward_list # error "__cpp_lib_constexpr_forward_list should not be defined before c++26" # endif @@ -2130,6 +2146,14 @@ # error "__cpp_lib_constexpr_dynamic_alloc should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_forward_list # error "__cpp_lib_constexpr_forward_list should not be defined before c++26" # endif @@ -3384,6 +3408,14 @@ # error "__cpp_lib_constexpr_dynamic_alloc should have the value 201907L in c++20" # endif +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_forward_list # error "__cpp_lib_constexpr_forward_list should not be defined before c++26" # endif @@ -4860,6 +4892,14 @@ # error "__cpp_lib_constexpr_dynamic_alloc should have the value 201907L in c++23" # endif +# ifdef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should not be defined before c++26" +# endif + +# ifdef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_forward_list # error "__cpp_lib_constexpr_forward_list should not be defined before c++26" # endif @@ -6549,6 +6589,20 @@ # error "__cpp_lib_constexpr_dynamic_alloc should have the value 201907L in c++26" # endif +# ifndef __cpp_lib_constexpr_flat_map +# error "__cpp_lib_constexpr_flat_map should be defined in c++26" +# endif +# if __cpp_lib_constexpr_flat_map != 202502L +# error "__cpp_lib_constexpr_flat_map should have the value 202502L in c++26" +# endif + +# ifndef __cpp_lib_constexpr_flat_set +# error "__cpp_lib_constexpr_flat_set should be defined in c++26" +# endif +# if __cpp_lib_constexpr_flat_set != 202502L +# error "__cpp_lib_constexpr_flat_set should have the value 202502L in c++26" +# endif + # ifndef __cpp_lib_constexpr_forward_list # error "__cpp_lib_constexpr_forward_list should be defined in c++26" # endif @@ -7256,7 +7310,7 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if __has_builtin(__builtin_is_within_lifetime) # ifndef __cpp_lib_is_within_lifetime # error "__cpp_lib_is_within_lifetime should be defined in c++26" # endif @@ -7265,7 +7319,7 @@ # endif # else # ifdef __cpp_lib_is_within_lifetime -# error "__cpp_lib_is_within_lifetime should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_is_within_lifetime should not be defined when the requirement '__has_builtin(__builtin_is_within_lifetime)' is not met!" # endif # endif diff --git a/libcxx/test/std/strings/basic.string/string.capacity/deallocate_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/deallocate_size.pass.cpp index 00f9e2b..ecdc397 100644 --- a/libcxx/test/std/strings/basic.string/string.capacity/deallocate_size.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.capacity/deallocate_size.pass.cpp @@ -12,12 +12,14 @@ #include <string> #include <cassert> +#include <cstddef> #include <cstdint> #include <type_traits> #include "test_macros.h" -static int allocated_; +static std::uint64_t allocated_; +static std::uint64_t deallocated_; template <class T, class Sz> struct test_alloc { @@ -41,12 +43,12 @@ struct test_alloc { pointer allocate(size_type n, const void* = nullptr) { allocated_ += n; - return std::allocator<value_type>().allocate(n); + return std::allocator<value_type>().allocate(static_cast<std::size_t>(n)); } void deallocate(pointer p, size_type s) { - allocated_ -= s; - std::allocator<value_type>().deallocate(p, s); + deallocated_ += s; + std::allocator<value_type>().deallocate(p, static_cast<std::size_t>(s)); } template <class U> @@ -64,14 +66,13 @@ struct test_alloc { template <class Sz> void test() { - for (int i = 1; i < 1000; ++i) { - using Str = std::basic_string<char, std::char_traits<char>, test_alloc<char, Sz> >; + for (unsigned int i = 1; i < 1000; ++i) { { - Str s(i, 't'); - assert(allocated_ == 0 || allocated_ >= i); + std::basic_string<char, std::char_traits<char>, test_alloc<char, Sz> > s(i, 't'); + (void)s; } + assert(allocated_ == deallocated_); } - assert(allocated_ == 0); } int main(int, char**) { diff --git a/libcxx/test/std/utilities/meta/meta.const.eval/is_within_lifetime.compile.pass.cpp b/libcxx/test/std/utilities/meta/meta.const.eval/is_within_lifetime.compile.pass.cpp new file mode 100644 index 0000000..40c2273 --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.const.eval/is_within_lifetime.compile.pass.cpp @@ -0,0 +1,148 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++11, c++14, c++17, c++20, c++23 +// UNSUPPORTED: gcc-15, apple-clang-17 + +// <type_traits> + +// template <class T> +// consteval bool is_within_lifetime(const T*) noexcept; // C++26 + +#include <cassert> +#include <type_traits> +#include <utility> + +#include "test_macros.h" + +ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<int*>())), bool); +ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<const int*>())), bool); +ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<void*>())), bool); +ASSERT_SAME_TYPE(decltype(std::is_within_lifetime(std::declval<const void*>())), bool); + +ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<int*>())); +ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<const int*>())); +ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<void*>())); +ASSERT_NOEXCEPT(std::is_within_lifetime(std::declval<const void*>())); + +template <class T> +concept is_within_lifetime_exists = requires(T t) { std::is_within_lifetime(t); }; + +struct S {}; + +static_assert(is_within_lifetime_exists<int*>); +static_assert(is_within_lifetime_exists<const int*>); +static_assert(is_within_lifetime_exists<void*>); +static_assert(is_within_lifetime_exists<const void*>); +static_assert(!is_within_lifetime_exists<int>); // Not a pointer +static_assert(!is_within_lifetime_exists<decltype(nullptr)>); // Not a pointer +static_assert(!is_within_lifetime_exists<void() const>); // Not a pointer +static_assert(!is_within_lifetime_exists<int S::*>); // Doesn't accept pointer-to-data-member +static_assert(!is_within_lifetime_exists<void (S::*)()>); // Doesn't accept pointer-to-member-function +static_assert(!is_within_lifetime_exists<void (*)()>); // Doesn't match `const T*` + +consteval bool f() { + // Test that it works with global variables whose lifetime is in a + // different constant expression + { + static constexpr int i = 0; + static_assert(std::is_within_lifetime(&i)); + // (Even when cast to a different type) + static_assert(std::is_within_lifetime(const_cast<int*>(&i))); + static_assert(std::is_within_lifetime(static_cast<const void*>(&i))); + static_assert(std::is_within_lifetime(static_cast<void*>(const_cast<int*>(&i)))); + static_assert(std::is_within_lifetime<const int>(&i)); + static_assert(std::is_within_lifetime<int>(const_cast<int*>(&i))); + static_assert(std::is_within_lifetime<const void>(static_cast<const void*>(&i))); + static_assert(std::is_within_lifetime<void>(static_cast<void*>(const_cast<int*>(&i)))); + } + + { + static constexpr union { + int member1; + int member2; + } u{.member2 = 1}; + static_assert(!std::is_within_lifetime(&u.member1) && std::is_within_lifetime(&u.member2)); + } + + // Test that it works for varibles inside the same constant expression + { + int i = 0; + assert(std::is_within_lifetime(&i)); + // (Even when cast to a different type) + assert(std::is_within_lifetime(const_cast<int*>(&i))); + assert(std::is_within_lifetime(static_cast<const void*>(&i))); + assert(std::is_within_lifetime(static_cast<void*>(const_cast<int*>(&i)))); + assert(std::is_within_lifetime<const int>(&i)); + assert(std::is_within_lifetime<int>(const_cast<int*>(&i))); + assert(std::is_within_lifetime<const void>(static_cast<const void*>(&i))); + assert(std::is_within_lifetime<void>(static_cast<void*>(const_cast<int*>(&i)))); + } + // Anonymous union + { + union { + int member1; + int member2; + }; + assert(!std::is_within_lifetime(&member1) && !std::is_within_lifetime(&member2)); + member1 = 1; + assert(std::is_within_lifetime(&member1) && !std::is_within_lifetime(&member2)); + member2 = 1; + assert(!std::is_within_lifetime(&member1) && std::is_within_lifetime(&member2)); + } + // Variant members + { + struct X { + union { + int member1; + int member2; + }; + } x; + assert(!std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2)); + x.member1 = 1; + assert(std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2)); + x.member2 = 1; + assert(!std::is_within_lifetime(&x.member1) && std::is_within_lifetime(&x.member2)); + } + // Unions + { + union X { + int member1; + int member2; + } x; + assert(!std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2)); + x.member1 = 1; + assert(std::is_within_lifetime(&x.member1) && !std::is_within_lifetime(&x.member2)); + x.member2 = 1; + assert(!std::is_within_lifetime(&x.member1) && std::is_within_lifetime(&x.member2)); + } + { + S s; // uninitialised + assert(std::is_within_lifetime(&s)); + } + + return true; +} +static_assert(f()); + +// Check that it is a consteval (and consteval-propagating) function +// (i.e., taking the address of below will fail because it will be an immediate function) +template <typename T> +constexpr void does_escalate(T p) { + std::is_within_lifetime(p); +} +template <typename T, void (*)(T) = &does_escalate<T>> +constexpr bool check_escalated(int) { + return false; +} +template <typename T> +constexpr bool check_escalated(long) { + return true; +} +static_assert(check_escalated<int*>(0), ""); +static_assert(check_escalated<void*>(0), ""); diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index f6f2527..22209f5 100644 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -369,6 +369,16 @@ feature_test_macros = [ "headers": ["memory"], }, { + "name": "__cpp_lib_constexpr_flat_map", + "values": {"c++26": 202502}, + "headers": ["flat_map"], + }, + { + "name": "__cpp_lib_constexpr_flat_set", + "values": {"c++26": 202502}, + "headers": ["flat_set"], + }, + { "name": "__cpp_lib_constexpr_forward_list", "values": {"c++26": 202502}, "headers": ["forward_list"], @@ -863,7 +873,8 @@ feature_test_macros = [ "c++26": 202306 # P2641R4 Checking if a union alternative is active }, "headers": ["type_traits"], - "unimplemented": True, + "test_suite_guard": "__has_builtin(__builtin_is_within_lifetime)", + "libcxx_guard": "__has_builtin(__builtin_is_within_lifetime)", }, { "name": "__cpp_lib_jthread", |
