diff options
Diffstat (limited to 'libcxx')
89 files changed, 1583 insertions, 549 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/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",  | 
