From 1f8dd2169e6bdebdc43856415d09af3783738fb8 Mon Sep 17 00:00:00 2001 From: Arendelle Date: Thu, 14 May 2026 15:36:22 +0800 Subject: [PATCH] string: fix constexpr compliance of basic_string default construction Replace raw pointer write `*ptr = 0` with `std::construct_at(ptr, char_type{})` in both `reset_imp()` and `string_allocate_init()`. In C++20 constexpr dynamic allocation, storage returned by `operator new` / `allocate_at_least` has not had its lifetime started; writing through the pointer without `std::construct_at` is ill-formed in a constant expression (Clang rejects it outright). Add constexpr_construct.cc test verifying `u8string{}` compiles and evaluates as a constant expression. --- include/fast_io_dsal/impl/string.h | 4 ++-- .../0004.string/constexpr_construct.cc | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/0026.container/0004.string/constexpr_construct.cc diff --git a/include/fast_io_dsal/impl/string.h b/include/fast_io_dsal/impl/string.h index a65eaa54e..fd509767d 100644 --- a/include/fast_io_dsal/impl/string.h +++ b/include/fast_io_dsal/impl/string.h @@ -34,7 +34,7 @@ inline constexpr ::fast_io::basic_allocation_least_result string_alloc // n is not possible to SIZE_MAX since that would overflow the memory which is not possible ::std::size_t const np1{static_cast<::std::size_t>(n + 1u)}; auto [ptr, allocn]{typed_allocator_type::allocate_at_least(np1)}; - *::fast_io::freestanding::non_overlapped_copy_n(first, n, ptr) = 0; + ::std::construct_at(::fast_io::freestanding::non_overlapped_copy_n(first, n, ptr), chtype{}); return {ptr, static_cast<::std::size_t>(allocn - 1u)}; } @@ -118,7 +118,7 @@ class basic_string FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE using untyped_allocator_type = generic_allocator_adapter; using typed_allocator_type = typed_generic_allocator_adapter; auto [ptr, cap]{typed_allocator_type::allocate_at_least(2)}; - *ptr = 0; + ::std::construct_at(ptr, char_type{}); this->imp = {ptr, ptr, ptr + static_cast(cap - 1u)}; } else diff --git a/tests/0026.container/0004.string/constexpr_construct.cc b/tests/0026.container/0004.string/constexpr_construct.cc new file mode 100644 index 000000000..f99707035 --- /dev/null +++ b/tests/0026.container/0004.string/constexpr_construct.cc @@ -0,0 +1,14 @@ +#include + +// Tests that default construction (reset_imp) works in constexpr context. +constexpr bool default_construct() +{ + ::fast_io::u8string s{}; + return s.empty(); +} +static_assert(default_construct()); + +int main() +{ + return 0; +}