diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h b/libstdc++-v3/include/bits/ranges_uninitialized.h index ced7bda5e37c..990929efaa9b 100644 --- a/libstdc++-v3/include/bits/ranges_uninitialized.h +++ b/libstdc++-v3/include/bits/ranges_uninitialized.h @@ -105,15 +105,18 @@ namespace ranges const _Iter* _M_cur; public: + constexpr explicit _DestroyGuard(const _Iter& __iter) : _M_first(__iter), _M_cur(std::__addressof(__iter)) { } + constexpr void release() noexcept { _M_cur = nullptr; } + constexpr ~_DestroyGuard() { if (_M_cur != nullptr) @@ -126,10 +129,12 @@ namespace ranges && is_trivially_destructible_v> struct _DestroyGuard<_Iter> { + constexpr explicit _DestroyGuard(const _Iter&) { } + constexpr void release() noexcept { } @@ -141,6 +146,7 @@ namespace ranges template<__detail::__nothrow_forward_iterator _Iter, __detail::__nothrow_sentinel<_Iter> _Sent> requires default_initializable> + _GLIBCXX26_CONSTEXPR _Iter operator()(_Iter __first, _Sent __last) const { @@ -159,6 +165,7 @@ namespace ranges template<__detail::__nothrow_forward_range _Range> requires default_initializable> + _GLIBCXX26_CONSTEXPR borrowed_iterator_t<_Range> operator()(_Range&& __r) const { @@ -173,6 +180,7 @@ namespace ranges { template<__detail::__nothrow_forward_iterator _Iter> requires default_initializable> + _GLIBCXX26_CONSTEXPR _Iter operator()(_Iter __first, iter_difference_t<_Iter> __n) const { @@ -198,6 +206,7 @@ namespace ranges template<__detail::__nothrow_forward_iterator _Iter, __detail::__nothrow_sentinel<_Iter> _Sent> requires default_initializable> + _GLIBCXX26_CONSTEXPR _Iter operator()(_Iter __first, _Sent __last) const { @@ -217,6 +226,7 @@ namespace ranges template<__detail::__nothrow_forward_range _Range> requires default_initializable> + _GLIBCXX26_CONSTEXPR borrowed_iterator_t<_Range> operator()(_Range&& __r) const { @@ -231,6 +241,7 @@ namespace ranges { template<__detail::__nothrow_forward_iterator _Iter> requires default_initializable> + _GLIBCXX26_CONSTEXPR _Iter operator()(_Iter __first, iter_difference_t<_Iter> __n) const { @@ -261,6 +272,7 @@ namespace ranges __detail::__nothrow_forward_iterator _Out, __detail::__nothrow_sentinel<_Out> _OSent> requires constructible_from, iter_reference_t<_Iter>> + _GLIBCXX26_CONSTEXPR uninitialized_copy_result<_Iter, _Out> operator()(_Iter __ifirst, _ISent __ilast, _Out __ofirst, _OSent __olast) const @@ -292,6 +304,7 @@ namespace ranges template requires constructible_from, range_reference_t<_IRange>> + _GLIBCXX26_CONSTEXPR uninitialized_copy_result, borrowed_iterator_t<_ORange>> operator()(_IRange&& __inr, _ORange&& __outr) const @@ -311,6 +324,7 @@ namespace ranges template _Sent> requires constructible_from, iter_reference_t<_Iter>> + _GLIBCXX26_CONSTEXPR uninitialized_copy_n_result<_Iter, _Out> operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, _Out __ofirst, _Sent __olast) const @@ -350,6 +364,7 @@ namespace ranges __detail::__nothrow_sentinel<_Out> _OSent> requires constructible_from, iter_rvalue_reference_t<_Iter>> + _GLIBCXX26_CONSTEXPR uninitialized_move_result<_Iter, _Out> operator()(_Iter __ifirst, _ISent __ilast, _Out __ofirst, _OSent __olast) const @@ -384,6 +399,7 @@ namespace ranges template requires constructible_from, range_rvalue_reference_t<_IRange>> + _GLIBCXX26_CONSTEXPR uninitialized_move_result, borrowed_iterator_t<_ORange>> operator()(_IRange&& __inr, _ORange&& __outr) const @@ -404,6 +420,7 @@ namespace ranges __detail::__nothrow_sentinel<_Out> _Sent> requires constructible_from, iter_rvalue_reference_t<_Iter>> + _GLIBCXX26_CONSTEXPR uninitialized_move_n_result<_Iter, _Out> operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, _Out __ofirst, _Sent __olast) const @@ -441,6 +458,7 @@ namespace ranges template<__detail::__nothrow_forward_iterator _Iter, __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> requires constructible_from, const _Tp&> + _GLIBCXX26_CONSTEXPR _Iter operator()(_Iter __first, _Sent __last, const _Tp& __x) const { @@ -460,6 +478,7 @@ namespace ranges template<__detail::__nothrow_forward_range _Range, typename _Tp> requires constructible_from, const _Tp&> + _GLIBCXX26_CONSTEXPR borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Tp& __x) const { @@ -473,6 +492,7 @@ namespace ranges { template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> requires constructible_from, const _Tp&> + _GLIBCXX26_CONSTEXPR _Iter operator()(_Iter __first, iter_difference_t<_Iter> __n, const _Tp& __x) const @@ -573,6 +593,7 @@ namespace ranges } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std + #endif // concepts #endif // C++20 #endif // _RANGES_UNINITIALIZED_H diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h index bd8235e901bd..23b8fb754710 100644 --- a/libstdc++-v3/include/bits/stl_construct.h +++ b/libstdc++-v3/include/bits/stl_construct.h @@ -144,6 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template + _GLIBCXX26_CONSTEXPR inline void _Construct_novalue(_T1* __p) { ::new(static_cast(__p)) _T1; } diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index ed836663a442..b1428db48b00 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -226,6 +226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Like std::copy, but does not require an initialized output range. */ template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator uninitialized_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result) @@ -256,6 +257,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Src = decltype(std::__niter_base(__first)); using _ValT = typename iterator_traits<_ForwardIterator>::value_type; +#if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26 + if consteval { + return std::__do_uninit_copy(__first, __last, __result); + } +#endif if constexpr (!__is_trivially_constructible(_ValT, decltype(*__first))) return std::__do_uninit_copy(__first, __last, __result); else if constexpr (__memcpyable<_Dest, _Src>::__value) @@ -381,6 +387,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Like std::fill, but does not require an initialized output range. */ template + _GLIBCXX26_CONSTEXPR inline void uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __x) @@ -400,6 +407,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++17-extensions" +#if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26 + if consteval { + return std::__do_uninit_fill(__first, __last, __x); + } +#endif if constexpr (__is_byte<_ValueType>::__value) if constexpr (is_same<_ValueType, _Tp>::value || is_integral<_Tp>::value) @@ -509,6 +521,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Like std::fill_n, but does not require an initialized output range. */ template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { @@ -522,6 +535,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ValueType; #if __cplusplus >= 201103L +#if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26 + if consteval { + return std::__do_uninit_fill_n(__first, __n, __x); + } +#endif if constexpr (__is_byte<_ValueType>::__value) if constexpr (is_integral<_Tp>::value) if constexpr (is_integral<_Size>::value) @@ -815,6 +833,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __uninitialized_default_1 { template + _GLIBCXX26_CONSTEXPR static void __uninit_default(_ForwardIterator __first, _ForwardIterator __last) { @@ -829,6 +848,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __uninitialized_default_1 { template + _GLIBCXX26_CONSTEXPR static void __uninit_default(_ForwardIterator __first, _ForwardIterator __last) { @@ -882,6 +902,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __uninitialized_default // Fills [first, last) with value-initialized value_types. template + _GLIBCXX26_CONSTEXPR inline void __uninitialized_default(_ForwardIterator __first, _ForwardIterator __last) @@ -979,6 +1000,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __uninitialized_default_novalue_1 { template + _GLIBCXX26_CONSTEXPR static void __uninit_default_novalue(_ForwardIterator __first, _ForwardIterator __last) @@ -994,6 +1016,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __uninitialized_default_novalue_1 { template + _GLIBCXX26_CONSTEXPR static void __uninit_default_novalue(_ForwardIterator, _ForwardIterator) { @@ -1004,6 +1027,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __uninitialized_default_novalue_n_1 { template + _GLIBCXX26_CONSTEXPR static _ForwardIterator __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) { @@ -1019,6 +1043,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __uninitialized_default_novalue_n_1 { template + _GLIBCXX26_CONSTEXPR static _ForwardIterator __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) { return std::next(__first, __n); } @@ -1027,6 +1052,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __uninitialized_default_novalue // Fills [first, last) with default-initialized value_types. template + _GLIBCXX26_CONSTEXPR inline void __uninitialized_default_novalue(_ForwardIterator __first, _ForwardIterator __last) @@ -1042,6 +1068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __uninitialized_default_novalue_n // Fills [first, first + n) with default-initialized value_types. template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) { @@ -1055,6 +1082,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template + _GLIBCXX26_CONSTEXPR _ForwardIterator __uninitialized_copy_n(_InputIterator __first, _Size __n, _ForwardIterator __result, input_iterator_tag) @@ -1068,6 +1096,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n, _ForwardIterator __result, @@ -1076,6 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template + _GLIBCXX26_CONSTEXPR pair<_InputIterator, _ForwardIterator> __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, _ForwardIterator __result, input_iterator_tag) @@ -1089,6 +1119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template + _GLIBCXX26_CONSTEXPR inline pair<_RandomAccessIterator, _ForwardIterator> __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, _ForwardIterator __result, @@ -1112,6 +1143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Like copy_n(), but does not require an initialized output range. */ template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator uninitialized_copy_n(_InputIterator __first, _Size __n, _ForwardIterator __result) @@ -1120,6 +1152,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented template + _GLIBCXX26_CONSTEXPR inline pair<_InputIterator, _ForwardIterator> __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, _ForwardIterator __result) @@ -1139,6 +1172,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @since C++17 */ template + _GLIBCXX26_CONSTEXPR inline void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) @@ -1154,6 +1188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @since C++17 */ template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __count) { @@ -1167,6 +1202,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @since C++17 */ template + _GLIBCXX26_CONSTEXPR inline void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) @@ -1182,6 +1218,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @since C++17 */ template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __count) { @@ -1197,6 +1234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @since C++17 */ template + _GLIBCXX26_CONSTEXPR inline _ForwardIterator uninitialized_move(_InputIterator __first, _InputIterator __last, _ForwardIterator __result) @@ -1215,6 +1253,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @since C++17 */ template + _GLIBCXX26_CONSTEXPR inline pair<_InputIterator, _ForwardIterator> uninitialized_move_n(_InputIterator __first, _Size __count, _ForwardIterator __result) diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 665b92acae5a..0cdc2e82fc55 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -521,6 +521,11 @@ ftms = { ftms = { name = raw_memory_algorithms; + values = { + v = 202411; + cxxmin = 26; + extra_cond = "__cpp_constexpr >= 202406L"; + }; values = { v = 201606; cxxmin = 17; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index b47b75a1ca97..ec52cba517fa 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -581,7 +581,12 @@ #undef __glibcxx_want_gcd_lcm #if !defined(__cpp_lib_raw_memory_algorithms) -# if (__cplusplus >= 201703L) +# if (__cplusplus > 202302L) && (__cpp_constexpr >= 202406L) +# define __glibcxx_raw_memory_algorithms 202411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_raw_memory_algorithms) +# define __cpp_lib_raw_memory_algorithms 202411L +# endif +# elif (__cplusplus >= 201703L) # define __glibcxx_raw_memory_algorithms 201606L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_raw_memory_algorithms) # define __cpp_lib_raw_memory_algorithms 201606L diff --git a/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc b/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc index c9edfb2c0ff1..450a6a7bfc6b 100644 --- a/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc +++ b/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc @@ -73,18 +73,30 @@ namespace std template T* addressof(T&) noexcept; #endif template +#if __cplusplus >= 202400L + constexpr +#endif ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result); #if __cplusplus >= 201103L template +#if __cplusplus >= 202400L + constexpr +#endif ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result); #endif template +#if __cplusplus >= 202400L + constexpr +#endif void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); template +#if __cplusplus >= 202400L + constexpr +#endif void uninitialized_fill_n(ForwardIterator first, Size n, const T& x); #if __cplusplus >= 201103L diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/feature_test_macro.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/feature_test_macro.cc new file mode 100644 index 000000000000..0252753aa664 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/feature_test_macro.cc @@ -0,0 +1,14 @@ +// { dg-do compile { target c++17 } } +// { dg-add-options no_pch } + +#include + +#ifndef __cpp_lib_raw_memory_algorithms +# error "Feature-test macro for raw memory algorithms missing" +#elif __cplusplus > 202302L +# if __cpp_lib_raw_memory_algorithms < 202411L +# error "Feature-test macro for raw memory algorithms has wrong value" +# endif +#elif __cpp_lib_raw_memory_algorithms < 201606L +# error "Feature-test macro for raw memory algorithms has wrong value" +#endif diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc new file mode 100644 index 000000000000..6f05b0ce309d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constexpr.cc @@ -0,0 +1,58 @@ +// { dg-do compile { target c++26 } } + +#include +#include +#include +#include +#include + +template +constexpr +bool +test01_impl(std::vector input) +{ + static_assert(std::copy_constructible); + static_assert(std::equality_comparable); + + const std::size_t input_size = input.size(); + std::allocator alloc; + T* ptr = alloc.allocate(input_size); + + std::uninitialized_copy(input.begin(), input.end(), ptr); + if (!std::equal(input.begin(), input.end(), ptr, ptr + input_size)) + return false; + std::destroy(ptr, ptr + input_size); + + std::uninitialized_copy_n(input.begin(), input_size, ptr); + if (!std::equal(input.begin(), input.end(), ptr, ptr + input_size)) + return false; + std::destroy_n(ptr, input_size); + + std::span output(ptr, ptr + input_size); + std::ranges::uninitialized_copy(input, output); + if (!std::ranges::equal(input, output)) + return false; + std::ranges::destroy(output); + + std::ranges::uninitialized_copy_n(input.begin(), input_size, ptr, ptr + input_size); + if (!std::ranges::equal(input.begin(), input.end(), ptr, ptr + input_size)) + return false; + std::ranges::destroy_n(ptr, input_size); + + alloc.deallocate(ptr, input_size); + return true; +} + +constexpr +bool +test01() +{ + return + test01_impl({'a', 'b', 'c'}) && + test01_impl({1, 2, 3, 4}) && + test01_impl({1.0, 2.0, 3.0, 4.0}) && + test01_impl({"a", "b", "cc", "dddd", "eeeeeeeeeeeeeeee"}) && + test01_impl>({ {0}, {0, 1}, {0, 1, 2}}); +} + +static_assert(test01()); diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc new file mode 100644 index 000000000000..db39c8b4d051 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/constexpr.cc @@ -0,0 +1,67 @@ +// { dg-do compile { target c++26 } } + +#include +#include +#include +#include +#include + +template +constexpr +bool +test01_impl() +{ + static_assert(std::default_initializable); + static_assert(std::equality_comparable); + + constexpr std::size_t size = 42; + std::allocator alloc; + T* ptr = alloc.allocate(size); + + auto check = [&]() -> bool + { + if constexpr (!std::is_trivially_default_constructible_v) + return std::all_of(ptr, ptr + size, [](auto &&x) { return x == T(); }); + else + return true; + }; + + std::uninitialized_default_construct(ptr, ptr + size); + if (!check()) + return false; + std::destroy(ptr, ptr + size); + + std::uninitialized_default_construct_n(ptr, size); + if (!check()) + return false; + std::destroy_n(ptr, size); + + std::span storage(ptr, ptr + size); + std::ranges::uninitialized_default_construct(storage); + if (!check()) + return false; + std::ranges::destroy(storage); + + std::ranges::uninitialized_default_construct_n(ptr, size); + if (!check()) + return false; + std::ranges::destroy_n(ptr, size); + + alloc.deallocate(ptr, size); + return true; +} + +constexpr +bool +test01() +{ + return + test01_impl() && + test01_impl() && + test01_impl() && + test01_impl() && + test01_impl>() && + test01_impl>(); +} + +static_assert(test01()); diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc new file mode 100644 index 000000000000..e43cd35a92d9 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/constexpr.cc @@ -0,0 +1,68 @@ +// { dg-do compile { target c++26 } } + +#include +#include +#include +#include +#include + +template +constexpr +bool +test01_impl(const U& value = U()) +{ + static_assert(std::constructible_from); + //static_assert(std::equality_comparable_with); // unique_ptr fails with nullptr_t + + constexpr std::size_t size = 42; + std::allocator alloc; + T* ptr = alloc.allocate(size); + + auto check = [&]() -> bool + { + return std::all_of(ptr, ptr + size, [&](auto &&x) { return x == value; }); + }; + + std::uninitialized_fill(ptr, ptr + size, value); + if (!check()) + return false; + std::destroy(ptr, ptr + size); + + std::uninitialized_fill_n(ptr, size, value); + if (!check()) + return false; + std::destroy_n(ptr, size); + + std::span storage(ptr, ptr + size); + std::ranges::uninitialized_fill(storage, value); + if (!check()) + return false; + std::ranges::destroy(storage); + + std::ranges::uninitialized_fill_n(ptr, size, value); + if (!check()) + return false; + std::ranges::destroy_n(ptr, size); + + alloc.deallocate(ptr, size); + return true; +} + +constexpr +bool +test01() +{ + return + test01_impl('\0') && + test01_impl('x') && + test01_impl(0) && + test01_impl(42) && + test01_impl(3.14) && + test01_impl() && + test01_impl(std::string("test")) && + test01_impl>() && + test01_impl>({1, 2, 3, 4}) && + test01_impl>(nullptr); +} + +static_assert(test01()); diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc new file mode 100644 index 000000000000..47403ae706dc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constexpr.cc @@ -0,0 +1,51 @@ +// { dg-do compile { target c++26 } } + +#include +#include +#include +#include +#include + +template +constexpr +bool +test01_impl(std::vector input) +{ + static_assert(std::move_constructible); + static_assert(std::equality_comparable); + + const std::size_t input_size = input.size(); + std::allocator alloc; + T* ptr = alloc.allocate(input_size); + + std::uninitialized_move(input.begin(), input.end(), ptr); + std::destroy(ptr, ptr + input_size); + + std::uninitialized_move_n(input.begin(), input_size, ptr); + std::destroy_n(ptr, input_size); + + std::span output(ptr, ptr + input_size); + std::ranges::uninitialized_move(input, output); + std::ranges::destroy(output); + + std::ranges::uninitialized_move_n(input.begin(), input_size, ptr, ptr + input_size); + std::ranges::destroy_n(ptr, input_size); + + alloc.deallocate(ptr, input_size); + return true; +} + +constexpr +bool +test01() +{ + return + test01_impl({'a', 'b', 'c'}) && + test01_impl({1, 2, 3, 4}) && + test01_impl({1.0, 2.0, 3.0, 4.0}) && + test01_impl({"a", "b", "cc", "dddd", "eeeeeeeeeeeeeeee"}) && + test01_impl>({ {0}, {0, 1}, {0, 1, 2}}) && + test01_impl>(std::vector>(10)); +} + +static_assert(test01()); diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc new file mode 100644 index 000000000000..55dfc59b5ef3 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/constexpr.cc @@ -0,0 +1,64 @@ +// { dg-do compile { target c++26 } } + +#include +#include +#include +#include +#include + +template +constexpr +bool +test01_impl() +{ + static_assert(std::default_initializable); + static_assert(std::equality_comparable); + + constexpr std::size_t size = 42; + std::allocator alloc; + T* ptr = alloc.allocate(size); + + auto check = [&]() -> bool + { + return std::all_of(ptr, ptr + size, [](auto &&x) { return x == T(); }); + }; + + std::uninitialized_value_construct(ptr, ptr + size); + if (!check()) + return false; + std::destroy(ptr, ptr + size); + + std::uninitialized_value_construct_n(ptr, size); + if (!check()) + return false; + std::destroy_n(ptr, size); + + std::span storage(ptr, ptr + size); + std::ranges::uninitialized_value_construct(storage); + if (!check()) + return false; + std::ranges::destroy(storage); + + std::ranges::uninitialized_value_construct_n(ptr, size); + if (!check()) + return false; + std::ranges::destroy_n(ptr, size); + + alloc.deallocate(ptr, size); + return true; +} + +constexpr +bool +test01() +{ + return + test01_impl() && + test01_impl() && + test01_impl() && + test01_impl() && + test01_impl>() && + test01_impl>(); +} + +static_assert(test01());