Skip to content

Commit e14aeaf

Browse files
authored
Merge pull request #1274 from SekaiArendelle/constexpr-string
string: support constexpr dynamic allocation in string_heap_dilate_uncheck
2 parents 7f93222 + 30b7482 commit e14aeaf

3 files changed

Lines changed: 90 additions & 20 deletions

File tree

include/fast_io_dsal/impl/string.h

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ inline constexpr ::fast_io::basic_allocation_least_result<chtype *> string_alloc
3434
// n is not possible to SIZE_MAX since that would overflow the memory which is not possible
3535
::std::size_t const np1{static_cast<::std::size_t>(n + 1u)};
3636
auto [ptr, allocn]{typed_allocator_type::allocate_at_least(np1)};
37-
::std::construct_at(::fast_io::freestanding::non_overlapped_copy_n(first, n, ptr), chtype{});
37+
*::fast_io::freestanding::non_overlapped_copy_n(first, n, ptr) = 0;
3838
return {ptr, static_cast<::std::size_t>(allocn - 1u)};
3939
}
4040

@@ -54,17 +54,36 @@ inline constexpr void string_heap_dilate_uncheck(::fast_io::containers::details:
5454
{
5555
beginptr = nullptr;
5656
}
57-
if constexpr (typed_allocator_type::has_reallocate)
57+
#if __cpp_constexpr_dynamic_alloc >= 201907L
58+
if consteval
5859
{
59-
auto [newptr, newcap] = typed_allocator_type::reallocate_at_least(beginptr, rsize + 1u);
60+
auto [newptr, newcap] = typed_allocator_type::allocate_at_least(rsize + 1u);
61+
if (beginptr != nullptr)
62+
{
63+
for (::std::size_t i{}; i != strsize; ++i)
64+
{
65+
::std::construct_at(newptr + i, beginptr[i]);
66+
}
67+
typed_allocator_type::deallocate_n(beginptr, bfsize);
68+
}
6069
ptr = newptr;
6170
rsize = newcap - 1u;
6271
}
6372
else
73+
#endif
6474
{
65-
auto [newptr, newcap] = typed_allocator_type::reallocate_n_at_least(beginptr, bfsize, rsize + 1u);
66-
ptr = newptr;
67-
rsize = newcap - 1u;
75+
if constexpr (typed_allocator_type::has_reallocate)
76+
{
77+
auto [newptr, newcap] = typed_allocator_type::reallocate_at_least(beginptr, rsize + 1u);
78+
ptr = newptr;
79+
rsize = newcap - 1u;
80+
}
81+
else
82+
{
83+
auto [newptr, newcap] = typed_allocator_type::reallocate_n_at_least(beginptr, bfsize, rsize + 1u);
84+
ptr = newptr;
85+
rsize = newcap - 1u;
86+
}
6887
}
6988
imp = {ptr, ptr + strsize, ptr + rsize};
7089
}

tests/0026.container/0004.string/constexpr_construct.cc

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include <fast_io_dsal/string.h>
2+
3+
// Tests that default construction (reset_imp) works in constexpr context.
4+
constexpr bool default_construct()
5+
{
6+
::fast_io::u8string s{};
7+
return s.empty();
8+
}
9+
static_assert(default_construct());
10+
11+
#if !(defined _MSC_VER && !defined __clang__)
12+
13+
// reserve at compile time (exercises string_heap_dilate_uncheck constexpr path)
14+
constexpr bool reserve_constexpr()
15+
{
16+
::fast_io::u8string s{};
17+
s.reserve(100);
18+
return s.capacity() >= 100;
19+
}
20+
static_assert(reserve_constexpr());
21+
22+
#endif
23+
24+
#if defined __GNUC__ && !defined __clang__
25+
// following tests compile with clang -fexperimental-new-constant-interpreter flag can pass
26+
// However, the default clang constant interpreter sucks
27+
28+
// push_back at compile time (exercises push_back + grow_twice constexpr path)
29+
constexpr bool push_back_constexpr()
30+
{
31+
::fast_io::u8string s{};
32+
s.push_back('a');
33+
s.push_back('b');
34+
return s.size() == 2 && s[0] == 'a' && s[1] == 'b';
35+
}
36+
static_assert(push_back_constexpr());
37+
38+
// Multiple push_back with growth at compile time
39+
constexpr bool push_back_many_constexpr()
40+
{
41+
::fast_io::u8string s{};
42+
for (char c = 'a'; c <= 'z'; ++c)
43+
{
44+
s.push_back(c);
45+
}
46+
return s.size() == 26;
47+
}
48+
static_assert(push_back_many_constexpr());
49+
50+
// clear at compile time
51+
constexpr bool clear_constexpr()
52+
{
53+
::fast_io::u8string s{};
54+
s.push_back('a');
55+
s.clear();
56+
return s.empty();
57+
}
58+
static_assert(clear_constexpr());
59+
60+
#endif
61+
62+
int main()
63+
{
64+
return 0;
65+
}

0 commit comments

Comments
 (0)