Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions include/fast_io_dsal/impl/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ inline constexpr ::fast_io::basic_allocation_least_result<chtype *> 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)};
}

Expand All @@ -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};
}
Expand Down
14 changes: 0 additions & 14 deletions tests/0026.container/0004.string/constexpr_construct.cc

This file was deleted.

65 changes: 65 additions & 0 deletions tests/0026.container/0004.string/constexpr_tests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <fast_io_dsal/string.h>

// 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;
}
Loading