diff --git a/include/fast_io_dsal/impl/string.h b/include/fast_io_dsal/impl/string.h index fd509767d..b114f82ea 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)}; - ::std::construct_at(::fast_io::freestanding::non_overlapped_copy_n(first, n, ptr), chtype{}); + *::fast_io::freestanding::non_overlapped_copy_n(first, n, ptr) = 0; return {ptr, static_cast<::std::size_t>(allocn - 1u)}; } @@ -54,17 +54,36 @@ inline constexpr void string_heap_dilate_uncheck(::fast_io::containers::details: { beginptr = nullptr; } - if constexpr (typed_allocator_type::has_reallocate) +#if __cpp_constexpr_dynamic_alloc >= 201907L + if consteval { - auto [newptr, newcap] = typed_allocator_type::reallocate_at_least(beginptr, rsize + 1u); + auto [newptr, newcap] = typed_allocator_type::allocate_at_least(rsize + 1u); + if (beginptr != nullptr) + { + for (::std::size_t i{}; i != strsize; ++i) + { + ::std::construct_at(newptr + i, beginptr[i]); + } + typed_allocator_type::deallocate_n(beginptr, bfsize); + } ptr = newptr; rsize = newcap - 1u; } else +#endif { - auto [newptr, newcap] = typed_allocator_type::reallocate_n_at_least(beginptr, bfsize, rsize + 1u); - ptr = newptr; - rsize = newcap - 1u; + if constexpr (typed_allocator_type::has_reallocate) + { + auto [newptr, newcap] = typed_allocator_type::reallocate_at_least(beginptr, rsize + 1u); + ptr = newptr; + rsize = newcap - 1u; + } + else + { + auto [newptr, newcap] = typed_allocator_type::reallocate_n_at_least(beginptr, bfsize, rsize + 1u); + ptr = newptr; + rsize = newcap - 1u; + } } imp = {ptr, ptr + strsize, ptr + rsize}; } diff --git a/tests/0026.container/0004.string/constexpr_construct.cc b/tests/0026.container/0004.string/constexpr_construct.cc deleted file mode 100644 index f99707035..000000000 --- a/tests/0026.container/0004.string/constexpr_construct.cc +++ /dev/null @@ -1,14 +0,0 @@ -#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; -} diff --git a/tests/0026.container/0004.string/constexpr_tests.cc b/tests/0026.container/0004.string/constexpr_tests.cc new file mode 100644 index 000000000..ec778089f --- /dev/null +++ b/tests/0026.container/0004.string/constexpr_tests.cc @@ -0,0 +1,65 @@ +#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()); + +#if !(defined _MSC_VER && !defined __clang__) + +// reserve at compile time (exercises string_heap_dilate_uncheck constexpr path) +constexpr bool reserve_constexpr() +{ + ::fast_io::u8string s{}; + s.reserve(100); + return s.capacity() >= 100; +} +static_assert(reserve_constexpr()); + +#endif + +#if defined __GNUC__ && !defined __clang__ +// following tests compile with clang -fexperimental-new-constant-interpreter flag can pass +// However, the default clang constant interpreter sucks + +// push_back at compile time (exercises push_back + grow_twice constexpr path) +constexpr bool push_back_constexpr() +{ + ::fast_io::u8string s{}; + s.push_back('a'); + s.push_back('b'); + return s.size() == 2 && s[0] == 'a' && s[1] == 'b'; +} +static_assert(push_back_constexpr()); + +// Multiple push_back with growth at compile time +constexpr bool push_back_many_constexpr() +{ + ::fast_io::u8string s{}; + for (char c = 'a'; c <= 'z'; ++c) + { + s.push_back(c); + } + return s.size() == 26; +} +static_assert(push_back_many_constexpr()); + +// clear at compile time +constexpr bool clear_constexpr() +{ + ::fast_io::u8string s{}; + s.push_back('a'); + s.clear(); + return s.empty(); +} +static_assert(clear_constexpr()); + +#endif + +int main() +{ + return 0; +}