1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // FIXME: This takes over an hour to compile, disable for now.
10 // UNSUPPORTED: LIBCXX-AMDGPU-FIXME
11 // UNSUPPORTED: LIBCXX-NVPTX-FIXME
12 
13 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
14 // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=10000000
15 // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=70000000
16 
17 // template<container-compatible-range<charT> R>
18 //   constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); // C++23
19 
20 #include <string>
21 #include <utility>
22 
23 #include "../../../../containers/sequences/insert_range_sequence_containers.h"
24 #include "test_macros.h"
25 
26 template <class Range>
27 concept HasReplaceWithRange =
28     requires(std::string& c, Range&& range) { c.replace_with_range(c.end(), c.end(), std::forward<Range>(range)); };
29 
30 constexpr bool test_constraints_replace_with_range() {
31   // Input range with the same value type.
32   static_assert(HasReplaceWithRange<InputRange<char>>);
33   // Input range with a convertible value type.
34   static_assert(HasReplaceWithRange<InputRange<unsigned char>>);
35   // Input range with a non-convertible value type.
36   static_assert(!HasReplaceWithRange<InputRange<Empty>>);
37   // Not an input range.
38   static_assert(!HasReplaceWithRange<InputRangeNotDerivedFrom>);
39   static_assert(!HasReplaceWithRange<InputRangeNotIndirectlyReadable>);
40   static_assert(!HasReplaceWithRange<InputRangeNotInputOrOutputIterator>);
41 
42   return true;
43 }
44 
45 using StrBuffer = Buffer<char, 256>;
46 
47 struct TestCaseReplacement {
48   StrBuffer initial;
49   std::size_t from = 0;
50   std::size_t to   = 0;
51   StrBuffer input;
52   StrBuffer expected;
53 };
54 
55 // Permutation matrix:
56 // - initial string: empty / one-element / n elements;
57 // - cut starts from: beginning / middle / end;
58 // - cut size: empty / one-element / several elements / until the end;
59 // - input range: empty / one-element / middle-sized / longer than SSO / longer than the current string capacity.
60 
61 // Empty string.
62 
63 constexpr TestCaseReplacement EmptyString_End_EmptyCut_EmptyRange{
64     .initial = "", .from = 0, .to = 0, .input = "", .expected = ""};
65 
66 constexpr TestCaseReplacement EmptyString_End_EmptyCut_OneElementRange{
67     .initial = "", .from = 0, .to = 0, .input = "a", .expected = "a"};
68 
69 constexpr TestCaseReplacement EmptyString_End_EmptyCut_MidRange{
70     .initial = "", .from = 0, .to = 0, .input = "aeiou", .expected = "aeiou"};
71 
72 constexpr TestCaseReplacement EmptyString_End_EmptyCut_LongRange{
73     .initial  = "",
74     .from     = 0,
75     .to       = 0,
76     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
77     .expected = "abcdefghijklmnopqrstuvwxyz0123456789"};
78 
79 // One-element string.
80 
81 constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_EmptyRange{
82     .initial = "B", .from = 0, .to = 0, .input = "", .expected = "B"};
83 
84 constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_OneElementRange{
85     .initial = "B", .from = 0, .to = 0, .input = "a", .expected = "aB"};
86 
87 constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_MidRange{
88     .initial = "B", .from = 0, .to = 0, .input = "aeiou", .expected = "aeiouB"};
89 
90 constexpr TestCaseReplacement OneElementString_Begin_EmptyCut_LongRange{
91     .initial  = "B",
92     .from     = 0,
93     .to       = 0,
94     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
95     .expected = "abcdefghijklmnopqrstuvwxyz0123456789B"};
96 
97 constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_EmptyRange{
98     .initial = "B", .from = 0, .to = 1, .input = "", .expected = ""};
99 
100 constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_OneElementRange{
101     .initial = "B", .from = 0, .to = 1, .input = "a", .expected = "a"};
102 
103 constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_MidRange{
104     .initial = "B", .from = 0, .to = 1, .input = "aeiou", .expected = "aeiou"};
105 
106 constexpr TestCaseReplacement OneElementString_Begin_OneElementCut_LongRange{
107     .initial  = "B",
108     .from     = 0,
109     .to       = 1,
110     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
111     .expected = "abcdefghijklmnopqrstuvwxyz0123456789"};
112 
113 constexpr TestCaseReplacement OneElementString_End_EmptyCut_EmptyRange{
114     .initial = "B", .from = 1, .to = 1, .input = "", .expected = "B"};
115 
116 constexpr TestCaseReplacement OneElementString_End_EmptyCut_OneElementRange{
117     .initial = "B", .from = 1, .to = 1, .input = "a", .expected = "Ba"};
118 
119 constexpr TestCaseReplacement OneElementString_End_EmptyCut_MidRange{
120     .initial = "B", .from = 1, .to = 1, .input = "aeiou", .expected = "Baeiou"};
121 
122 constexpr TestCaseReplacement OneElementString_End_EmptyCut_LongRange{
123     .initial  = "B",
124     .from     = 1,
125     .to       = 1,
126     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
127     .expected = "Babcdefghijklmnopqrstuvwxyz0123456789"};
128 
129 // Short string (using SSO).
130 
131 // Replace at the beginning.
132 
133 constexpr TestCaseReplacement ShortString_Begin_EmptyCut_EmptyRange{
134     .initial = "_BCDFGHJ_", .from = 0, .to = 0, .input = "", .expected = "_BCDFGHJ_"};
135 
136 constexpr TestCaseReplacement ShortString_Begin_EmptyCut_OneElementRange{
137     .initial = "_BCDFGHJ_", .from = 0, .to = 0, .input = "a", .expected = "a_BCDFGHJ_"};
138 
139 constexpr TestCaseReplacement ShortString_Begin_EmptyCut_MidRange{
140     .initial = "_BCDFGHJ_", .from = 0, .to = 0, .input = "aeiou", .expected = "aeiou_BCDFGHJ_"};
141 
142 constexpr TestCaseReplacement ShortString_Begin_EmptyCut_LongRange{
143     .initial  = "_BCDFGHJ_",
144     .from     = 0,
145     .to       = 0,
146     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
147     .expected = "abcdefghijklmnopqrstuvwxyz0123456789_BCDFGHJ_"};
148 
149 constexpr TestCaseReplacement ShortString_Begin_OneElementCut_EmptyRange{
150     .initial = "_BCDFGHJ_", .from = 0, .to = 1, .input = "", .expected = "BCDFGHJ_"};
151 
152 constexpr TestCaseReplacement ShortString_Begin_OneElementCut_OneElementRange{
153     .initial = "_BCDFGHJ_", .from = 0, .to = 1, .input = "a", .expected = "aBCDFGHJ_"};
154 
155 constexpr TestCaseReplacement ShortString_Begin_OneElementCut_MidRange{
156     .initial = "_BCDFGHJ_", .from = 0, .to = 1, .input = "aeiou", .expected = "aeiouBCDFGHJ_"};
157 
158 constexpr TestCaseReplacement ShortString_Begin_OneElementCut_LongRange{
159     .initial  = "_BCDFGHJ_",
160     .from     = 0,
161     .to       = 1,
162     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
163     .expected = "abcdefghijklmnopqrstuvwxyz0123456789BCDFGHJ_"};
164 
165 constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_EmptyRange{
166     .initial = "_BCDFGHJ_", .from = 0, .to = 3, .input = "", .expected = "DFGHJ_"};
167 
168 constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_OneElementRange{
169     .initial = "_BCDFGHJ_", .from = 0, .to = 3, .input = "a", .expected = "aDFGHJ_"};
170 
171 constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_MidRange{
172     .initial = "_BCDFGHJ_", .from = 0, .to = 3, .input = "aeiou", .expected = "aeiouDFGHJ_"};
173 
174 // Note: this test case switches from SSO to non-SSO.
175 constexpr TestCaseReplacement ShortString_Begin_MidSizedCut_LongRange{
176     .initial  = "_BCDFGHJ_",
177     .from     = 0,
178     .to       = 3,
179     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
180     .expected = "abcdefghijklmnopqrstuvwxyz0123456789DFGHJ_"};
181 
182 constexpr TestCaseReplacement ShortString_Begin_CutToEnd_EmptyRange{
183     .initial = "_BCDFGHJ_", .from = 0, .to = 9, .input = "", .expected = ""};
184 
185 constexpr TestCaseReplacement ShortString_Begin_CutToEnd_OneElementRange{
186     .initial = "_BCDFGHJ_", .from = 0, .to = 9, .input = "a", .expected = "a"};
187 
188 constexpr TestCaseReplacement ShortString_Begin_CutToEnd_MidRange{
189     .initial = "_BCDFGHJ_", .from = 0, .to = 9, .input = "aeiou", .expected = "aeiou"};
190 
191 // Note: this test case switches from SSO to non-SSO.
192 constexpr TestCaseReplacement ShortString_Begin_CutToEnd_LongRange{
193     .initial  = "_BCDFGHJ_",
194     .from     = 0,
195     .to       = 9,
196     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
197     .expected = "abcdefghijklmnopqrstuvwxyz0123456789"};
198 
199 // Replace in the middle.
200 
201 constexpr TestCaseReplacement ShortString_Mid_EmptyCut_EmptyRange{
202     .initial = "_BCDFGHJ_", .from = 4, .to = 4, .input = "", .expected = "_BCDFGHJ_"};
203 
204 constexpr TestCaseReplacement ShortString_Mid_EmptyCut_OneElementRange{
205     .initial = "_BCDFGHJ_", .from = 4, .to = 4, .input = "a", .expected = "_BCDaFGHJ_"};
206 
207 constexpr TestCaseReplacement ShortString_Mid_EmptyCut_MidRange{
208     .initial = "_BCDFGHJ_", .from = 4, .to = 4, .input = "aeiou", .expected = "_BCDaeiouFGHJ_"};
209 
210 constexpr TestCaseReplacement ShortString_Mid_EmptyCut_LongRange{
211     .initial  = "_BCDFGHJ_",
212     .from     = 4,
213     .to       = 4,
214     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
215     .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789FGHJ_"};
216 
217 constexpr TestCaseReplacement ShortString_Mid_OneElementCut_EmptyRange{
218     .initial = "_BCDFGHJ_", .from = 4, .to = 5, .input = "", .expected = "_BCDGHJ_"};
219 
220 constexpr TestCaseReplacement ShortString_Mid_OneElementCut_OneElementRange{
221     .initial = "_BCDFGHJ_", .from = 4, .to = 5, .input = "a", .expected = "_BCDaGHJ_"};
222 
223 constexpr TestCaseReplacement ShortString_Mid_OneElementCut_MidRange{
224     .initial = "_BCDFGHJ_", .from = 4, .to = 5, .input = "aeiou", .expected = "_BCDaeiouGHJ_"};
225 
226 constexpr TestCaseReplacement ShortString_Mid_OneElementCut_LongRange{
227     .initial  = "_BCDFGHJ_",
228     .from     = 4,
229     .to       = 5,
230     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
231     .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789GHJ_"};
232 
233 constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_EmptyRange{
234     .initial = "_BCDFGHJ_", .from = 4, .to = 7, .input = "", .expected = "_BCDJ_"};
235 
236 constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_OneElementRange{
237     .initial = "_BCDFGHJ_", .from = 4, .to = 7, .input = "a", .expected = "_BCDaJ_"};
238 
239 constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_MidRange{
240     .initial = "_BCDFGHJ_", .from = 4, .to = 7, .input = "aeiou", .expected = "_BCDaeiouJ_"};
241 
242 constexpr TestCaseReplacement ShortString_Mid_MidSizedCut_LongRange{
243     .initial  = "_BCDFGHJ_",
244     .from     = 4,
245     .to       = 7,
246     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
247     .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789J_"};
248 
249 constexpr TestCaseReplacement ShortString_Mid_CutToEnd_EmptyRange{
250     .initial = "_BCDFGHJ_", .from = 4, .to = 9, .input = "", .expected = "_BCD"};
251 
252 constexpr TestCaseReplacement ShortString_Mid_CutToEnd_OneElementRange{
253     .initial = "_BCDFGHJ_", .from = 4, .to = 9, .input = "a", .expected = "_BCDa"};
254 
255 constexpr TestCaseReplacement ShortString_Mid_CutToEnd_MidRange{
256     .initial = "_BCDFGHJ_", .from = 4, .to = 9, .input = "aeiou", .expected = "_BCDaeiou"};
257 
258 constexpr TestCaseReplacement ShortString_Mid_CutToEnd_LongRange{
259     .initial  = "_BCDFGHJ_",
260     .from     = 4,
261     .to       = 9,
262     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
263     .expected = "_BCDabcdefghijklmnopqrstuvwxyz0123456789"};
264 
265 // Replace at the end.
266 
267 constexpr TestCaseReplacement ShortString_End_EmptyCut_EmptyRange{
268     .initial = "_BCDFGHJ_", .from = 9, .to = 9, .input = "", .expected = "_BCDFGHJ_"};
269 
270 constexpr TestCaseReplacement ShortString_End_EmptyCut_OneElementRange{
271     .initial = "_BCDFGHJ_", .from = 9, .to = 9, .input = "a", .expected = "_BCDFGHJ_a"};
272 
273 constexpr TestCaseReplacement ShortString_End_EmptyCut_MidRange{
274     .initial = "_BCDFGHJ_", .from = 9, .to = 9, .input = "aeiou", .expected = "_BCDFGHJ_aeiou"};
275 
276 constexpr TestCaseReplacement ShortString_End_EmptyCut_LongRange{
277     .initial  = "_BCDFGHJ_",
278     .from     = 9,
279     .to       = 9,
280     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
281     .expected = "_BCDFGHJ_abcdefghijklmnopqrstuvwxyz0123456789"};
282 
283 // Long string (no SSO).
284 
285 // Replace at the beginning.
286 
287 constexpr TestCaseReplacement LongString_Begin_EmptyCut_EmptyRange{
288     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
289     .from     = 0,
290     .to       = 0,
291     .input    = "",
292     .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
293 
294 constexpr TestCaseReplacement LongString_Begin_EmptyCut_OneElementRange{
295     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
296     .from     = 0,
297     .to       = 0,
298     .input    = "a",
299     .expected = "a_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
300 
301 constexpr TestCaseReplacement LongString_Begin_EmptyCut_MidRange{
302     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
303     .from     = 0,
304     .to       = 0,
305     .input    = "aeiou",
306     .expected = "aeiou_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
307 
308 constexpr TestCaseReplacement LongString_Begin_EmptyCut_LongRange{
309     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
310     .from     = 0,
311     .to       = 0,
312     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
313     .expected = "abcdefghijklmnopqrstuvwxyz0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
314 
315 constexpr TestCaseReplacement LongString_Begin_EmptyCut_LongerThanCapacityRange{
316     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
317     .from     = 0,
318     .to       = 0,
319     .input    = "abcdefghijklmnopqrstuvwxyz0123456789_"
320                 "abcdefghijklmnopqrstuvwxyz0123456789_"
321                 "abcdefghijklmnopqrstuvwxyz0123456789",
322     .expected = "abcdefghijklmnopqrstuvwxyz0123456789_"
323                 "abcdefghijklmnopqrstuvwxyz0123456789_"
324                 "abcdefghijklmnopqrstuvwxyz0123456789"
325                 "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
326 
327 constexpr TestCaseReplacement LongString_Begin_OneElementCut_EmptyRange{
328     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
329     .from     = 0,
330     .to       = 1,
331     .input    = "",
332     .expected = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
333 
334 constexpr TestCaseReplacement LongString_Begin_OneElementCut_OneElementRange{
335     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
336     .from     = 0,
337     .to       = 1,
338     .input    = "a",
339     .expected = "aABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
340 
341 constexpr TestCaseReplacement LongString_Begin_OneElementCut_MidRange{
342     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
343     .from     = 0,
344     .to       = 1,
345     .input    = "aeiou",
346     .expected = "aeiouABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
347 
348 constexpr TestCaseReplacement LongString_Begin_OneElementCut_LongRange{
349     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
350     .from     = 0,
351     .to       = 1,
352     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
353     .expected = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
354 
355 constexpr TestCaseReplacement LongString_Begin_OneElementCut_LongerThanCapacityRange{
356     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
357     .from     = 0,
358     .to       = 1,
359     .input    = "abcdefghijklmnopqrstuvwxyz0123456789_"
360                 "abcdefghijklmnopqrstuvwxyz0123456789_"
361                 "abcdefghijklmnopqrstuvwxyz0123456789",
362     .expected = "abcdefghijklmnopqrstuvwxyz0123456789_"
363                 "abcdefghijklmnopqrstuvwxyz0123456789_"
364                 "abcdefghijklmnopqrstuvwxyz0123456789"
365                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
366 
367 constexpr TestCaseReplacement LongString_Begin_MidSizedCut_EmptyRange{
368     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
369     .from     = 0,
370     .to       = 3,
371     .input    = "",
372     .expected = "CDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
373 
374 constexpr TestCaseReplacement LongString_Begin_MidSizedCut_OneElementRange{
375     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
376     .from     = 0,
377     .to       = 3,
378     .input    = "a",
379     .expected = "aCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
380 
381 constexpr TestCaseReplacement LongString_Begin_MidSizedCut_MidRange{
382     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
383     .from     = 0,
384     .to       = 3,
385     .input    = "aeiou",
386     .expected = "aeiouCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
387 
388 constexpr TestCaseReplacement LongString_Begin_MidSizedCut_LongRange{
389     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
390     .from     = 0,
391     .to       = 3,
392     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
393     .expected = "abcdefghijklmnopqrstuvwxyz0123456789CDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
394 
395 constexpr TestCaseReplacement LongString_Begin_MidSizedCut_LongerThanCapacityRange{
396     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
397     .from     = 0,
398     .to       = 3,
399     .input    = "abcdefghijklmnopqrstuvwxyz0123456789_"
400                 "abcdefghijklmnopqrstuvwxyz0123456789_"
401                 "abcdefghijklmnopqrstuvwxyz0123456789",
402     .expected = "abcdefghijklmnopqrstuvwxyz0123456789_"
403                 "abcdefghijklmnopqrstuvwxyz0123456789_"
404                 "abcdefghijklmnopqrstuvwxyz0123456789"
405                 "CDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
406 
407 constexpr TestCaseReplacement LongString_Begin_CutToEnd_EmptyRange{
408     .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "", .expected = ""};
409 
410 constexpr TestCaseReplacement LongString_Begin_CutToEnd_OneElementRange{
411     .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "a", .expected = "a"};
412 
413 constexpr TestCaseReplacement LongString_Begin_CutToEnd_MidRange{
414     .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_", .from = 0, .to = 38, .input = "aeiou", .expected = "aeiou"};
415 
416 constexpr TestCaseReplacement LongString_Begin_CutToEnd_LongRange{
417     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
418     .from     = 0,
419     .to       = 38,
420     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
421     .expected = "abcdefghijklmnopqrstuvwxyz0123456789"};
422 
423 constexpr TestCaseReplacement LongString_Begin_CutToEnd_LongerThanCapacityRange{
424     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
425     .from     = 0,
426     .to       = 38,
427     .input    = "abcdefghijklmnopqrstuvwxyz0123456789_"
428                 "abcdefghijklmnopqrstuvwxyz0123456789_"
429                 "abcdefghijklmnopqrstuvwxyz0123456789",
430     .expected = "abcdefghijklmnopqrstuvwxyz0123456789_"
431                 "abcdefghijklmnopqrstuvwxyz0123456789_"
432                 "abcdefghijklmnopqrstuvwxyz0123456789"};
433 
434 // Replace in the middle.
435 
436 constexpr TestCaseReplacement LongString_Mid_EmptyCut_EmptyRange{
437     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
438     .from     = 18,
439     .to       = 18,
440     .input    = "",
441     .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
442 
443 constexpr TestCaseReplacement LongString_Mid_EmptyCut_OneElementRange{
444     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
445     .from     = 18,
446     .to       = 18,
447     .input    = "a",
448     .expected = "_ABCDEFGHIJKLMNOPQaRSTUVWXYZ0123456789_"};
449 
450 constexpr TestCaseReplacement LongString_Mid_EmptyCut_MidRange{
451     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
452     .from     = 18,
453     .to       = 18,
454     .input    = "aeiou",
455     .expected = "_ABCDEFGHIJKLMNOPQaeiouRSTUVWXYZ0123456789_"};
456 
457 constexpr TestCaseReplacement LongString_Mid_EmptyCut_LongRange{
458     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
459     .from     = 18,
460     .to       = 18,
461     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
462     .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789RSTUVWXYZ0123456789_"};
463 
464 constexpr TestCaseReplacement LongString_Mid_EmptyCut_LongerThanCapacityRange{
465     .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
466     .from    = 18,
467     .to      = 18,
468     .input   = "abcdefghijklmnopqrstuvwxyz0123456789_"
469                "abcdefghijklmnopqrstuvwxyz0123456789_"
470                "abcdefghijklmnopqrstuvwxyz0123456789",
471     .expected =
472         "_ABCDEFGHIJKLMNOPQ"
473         "abcdefghijklmnopqrstuvwxyz0123456789_"
474         "abcdefghijklmnopqrstuvwxyz0123456789_"
475         "abcdefghijklmnopqrstuvwxyz0123456789"
476         "RSTUVWXYZ0123456789_"};
477 
478 constexpr TestCaseReplacement LongString_Mid_OneElementCut_EmptyRange{
479     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
480     .from     = 18,
481     .to       = 19,
482     .input    = "",
483     .expected = "_ABCDEFGHIJKLMNOPQSTUVWXYZ0123456789_"};
484 
485 constexpr TestCaseReplacement LongString_Mid_OneElementCut_OneElementRange{
486     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
487     .from     = 18,
488     .to       = 19,
489     .input    = "a",
490     .expected = "_ABCDEFGHIJKLMNOPQaSTUVWXYZ0123456789_"};
491 
492 constexpr TestCaseReplacement LongString_Mid_OneElementCut_MidRange{
493     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
494     .from     = 18,
495     .to       = 19,
496     .input    = "aeiou",
497     .expected = "_ABCDEFGHIJKLMNOPQaeiouSTUVWXYZ0123456789_"};
498 
499 constexpr TestCaseReplacement LongString_Mid_OneElementCut_LongRange{
500     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
501     .from     = 18,
502     .to       = 19,
503     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
504     .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789STUVWXYZ0123456789_"};
505 
506 constexpr TestCaseReplacement LongString_Mid_OneElementCut_LongerThanCapacityRange{
507     .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
508     .from    = 18,
509     .to      = 19,
510     .input   = "abcdefghijklmnopqrstuvwxyz0123456789_"
511                "abcdefghijklmnopqrstuvwxyz0123456789_"
512                "abcdefghijklmnopqrstuvwxyz0123456789",
513     .expected =
514         "_ABCDEFGHIJKLMNOPQ"
515         "abcdefghijklmnopqrstuvwxyz0123456789_"
516         "abcdefghijklmnopqrstuvwxyz0123456789_"
517         "abcdefghijklmnopqrstuvwxyz0123456789"
518         "STUVWXYZ0123456789_"};
519 
520 constexpr TestCaseReplacement LongString_Mid_MidSizedCut_EmptyRange{
521     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
522     .from     = 18,
523     .to       = 21,
524     .input    = "",
525     .expected = "_ABCDEFGHIJKLMNOPQUVWXYZ0123456789_"};
526 
527 constexpr TestCaseReplacement LongString_Mid_MidSizedCut_OneElementRange{
528     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
529     .from     = 18,
530     .to       = 21,
531     .input    = "a",
532     .expected = "_ABCDEFGHIJKLMNOPQaUVWXYZ0123456789_"};
533 
534 constexpr TestCaseReplacement LongString_Mid_MidSizedCut_MidRange{
535     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
536     .from     = 18,
537     .to       = 21,
538     .input    = "aeiou",
539     .expected = "_ABCDEFGHIJKLMNOPQaeiouUVWXYZ0123456789_"};
540 
541 constexpr TestCaseReplacement LongString_Mid_MidSizedCut_LongRange{
542     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
543     .from     = 18,
544     .to       = 21,
545     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
546     .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789UVWXYZ0123456789_"};
547 
548 constexpr TestCaseReplacement LongString_Mid_MidSizedCut_LongerThanCapacityRange{
549     .initial = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
550     .from    = 18,
551     .to      = 21,
552     .input   = "abcdefghijklmnopqrstuvwxyz0123456789_"
553                "abcdefghijklmnopqrstuvwxyz0123456789_"
554                "abcdefghijklmnopqrstuvwxyz0123456789",
555     .expected =
556         "_ABCDEFGHIJKLMNOPQ"
557         "abcdefghijklmnopqrstuvwxyz0123456789_"
558         "abcdefghijklmnopqrstuvwxyz0123456789_"
559         "abcdefghijklmnopqrstuvwxyz0123456789"
560         "UVWXYZ0123456789_"};
561 
562 constexpr TestCaseReplacement LongString_Mid_CutToEnd_EmptyRange{
563     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
564     .from     = 18,
565     .to       = 38,
566     .input    = "",
567     .expected = "_ABCDEFGHIJKLMNOPQ"};
568 
569 constexpr TestCaseReplacement LongString_Mid_CutToEnd_OneElementRange{
570     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
571     .from     = 18,
572     .to       = 38,
573     .input    = "a",
574     .expected = "_ABCDEFGHIJKLMNOPQa"};
575 
576 constexpr TestCaseReplacement LongString_Mid_CutToEnd_MidRange{
577     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
578     .from     = 18,
579     .to       = 38,
580     .input    = "aeiou",
581     .expected = "_ABCDEFGHIJKLMNOPQaeiou"};
582 
583 constexpr TestCaseReplacement LongString_Mid_CutToEnd_LongRange{
584     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
585     .from     = 18,
586     .to       = 38,
587     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
588     .expected = "_ABCDEFGHIJKLMNOPQabcdefghijklmnopqrstuvwxyz0123456789"};
589 
590 constexpr TestCaseReplacement LongString_Mid_CutToEnd_LongerThanCapacityRange{
591     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
592     .from     = 18,
593     .to       = 38,
594     .input    = "abcdefghijklmnopqrstuvwxyz0123456789_"
595                 "abcdefghijklmnopqrstuvwxyz0123456789_"
596                 "abcdefghijklmnopqrstuvwxyz0123456789",
597     .expected = "_ABCDEFGHIJKLMNOPQ"
598                 "abcdefghijklmnopqrstuvwxyz0123456789_"
599                 "abcdefghijklmnopqrstuvwxyz0123456789_"
600                 "abcdefghijklmnopqrstuvwxyz0123456789"};
601 
602 // Replace at the end.
603 
604 constexpr TestCaseReplacement LongString_End_EmptyCut_EmptyRange{
605     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
606     .from     = 38,
607     .to       = 38,
608     .input    = "",
609     .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"};
610 
611 constexpr TestCaseReplacement LongString_End_EmptyCut_OneElementRange{
612     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
613     .from     = 38,
614     .to       = 38,
615     .input    = "a",
616     .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_a"};
617 
618 constexpr TestCaseReplacement LongString_End_EmptyCut_MidRange{
619     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
620     .from     = 38,
621     .to       = 38,
622     .input    = "aeiou",
623     .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_aeiou"};
624 
625 constexpr TestCaseReplacement LongString_End_EmptyCut_LongRange{
626     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
627     .from     = 38,
628     .to       = 38,
629     .input    = "abcdefghijklmnopqrstuvwxyz0123456789",
630     .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_abcdefghijklmnopqrstuvwxyz0123456789"};
631 
632 constexpr TestCaseReplacement LongString_End_EmptyCut_LongerThanCapacityRange{
633     .initial  = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",
634     .from     = 38,
635     .to       = 38,
636     .input    = "abcdefghijklmnopqrstuvwxyz0123456789_"
637                 "abcdefghijklmnopqrstuvwxyz0123456789_"
638                 "abcdefghijklmnopqrstuvwxyz0123456789",
639     .expected = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
640                 "abcdefghijklmnopqrstuvwxyz0123456789_"
641                 "abcdefghijklmnopqrstuvwxyz0123456789_"
642                 "abcdefghijklmnopqrstuvwxyz0123456789"};
643 
644 template <class Iter, class Sent, class Alloc>
645 constexpr void test_string_replace_with_range() {
646   auto test = [&](const TestCaseReplacement& test_case) {
647     using Container = std::basic_string<char, std::char_traits<char>, Alloc>;
648 
649     auto get_pos = [](auto& c, auto index) { return std::ranges::next(c.begin(), index); };
650     Container c(test_case.initial.begin(), test_case.initial.end());
651     auto in   = wrap_input<Iter, Sent>(test_case.input);
652     auto from = get_pos(c, test_case.from);
653     auto to   = get_pos(c, test_case.to);
654 
655     Container& result = c.replace_with_range(from, to, in);
656     assert(&result == &c);
657     LIBCPP_ASSERT(c.__invariants());
658     return std::ranges::equal(c, test_case.expected);
659   };
660 
661   { // Empty string.
662     // empty_str.replace_with_range(end, end, empty_range)
663     assert(test(EmptyString_End_EmptyCut_EmptyRange));
664     // empty_str.replace_with_range(end, end, one_element_range)
665     assert(test(EmptyString_End_EmptyCut_OneElementRange));
666     // empty_str.replace_with_range(end, end, mid_range)
667     assert(test(EmptyString_End_EmptyCut_MidRange));
668     // empty_str.replace_with_range(end, end, long_range)
669     assert(test(EmptyString_End_EmptyCut_LongRange));
670   }
671 
672   { // One-element string.
673     // one_element_str.replace_with_range(begin, begin, empty_range)
674     assert(test(OneElementString_Begin_EmptyCut_EmptyRange));
675     // one_element_str.replace_with_range(begin, begin, one_element_range)
676     assert(test(OneElementString_Begin_EmptyCut_OneElementRange));
677     // one_element_str.replace_with_range(begin, begin, mid_range)
678     assert(test(OneElementString_Begin_EmptyCut_MidRange));
679     // one_element_str.replace_with_range(begin, begin, long_range)
680     assert(test(OneElementString_Begin_EmptyCut_LongRange));
681     // one_element_str.replace_with_range(begin, begin + 1, empty_range)
682     assert(test(OneElementString_Begin_OneElementCut_EmptyRange));
683     // one_element_str.replace_with_range(begin, begin + 1, one_element_range)
684     assert(test(OneElementString_Begin_OneElementCut_OneElementRange));
685     // one_element_str.replace_with_range(begin, begin + 1, mid_range)
686     assert(test(OneElementString_Begin_OneElementCut_MidRange));
687     // one_element_str.replace_with_range(begin, begin + 1, long_range)
688     assert(test(OneElementString_Begin_OneElementCut_LongRange));
689     // one_element_str.replace_with_range(end, end, empty_range)
690     assert(test(OneElementString_End_EmptyCut_EmptyRange));
691     // one_element_str.replace_with_range(end, end, one_element_range)
692     assert(test(OneElementString_End_EmptyCut_OneElementRange));
693     // one_element_str.replace_with_range(end, end, mid_range)
694     assert(test(OneElementString_End_EmptyCut_MidRange));
695     // one_element_str.replace_with_range(end, end, long_range)
696     assert(test(OneElementString_End_EmptyCut_LongRange));
697   }
698 
699   { // Short string.
700     // Replace at the beginning.
701 
702     // short_str.replace_with_range(begin, begin, empty_range)
703     assert(test(ShortString_Begin_EmptyCut_EmptyRange));
704     // short_str.replace_with_range(begin, begin, one_element_range)
705     assert(test(ShortString_Begin_EmptyCut_OneElementRange));
706     // short_str.replace_with_range(begin, begin, mid_range)
707     assert(test(ShortString_Begin_EmptyCut_MidRange));
708     // short_str.replace_with_range(begin, begin, long_range)
709     assert(test(ShortString_Begin_EmptyCut_LongRange));
710     // short_str.replace_with_range(begin, begin + 1, empty_range)
711     assert(test(ShortString_Begin_OneElementCut_EmptyRange));
712     // short_str.replace_with_range(begin, begin + 1, one_element_range)
713     assert(test(ShortString_Begin_OneElementCut_OneElementRange));
714     // short_str.replace_with_range(begin, begin + 1, mid_range)
715     assert(test(ShortString_Begin_OneElementCut_MidRange));
716     // short_str.replace_with_range(begin, begin + 1, long_range)
717     assert(test(ShortString_Begin_OneElementCut_LongRange));
718     // short_str.replace_with_range(begin, begin + 3, empty_range)
719     assert(test(ShortString_Begin_MidSizedCut_EmptyRange));
720     // short_str.replace_with_range(begin, begin + 3, one_element_range)
721     assert(test(ShortString_Begin_MidSizedCut_OneElementRange));
722     // short_str.replace_with_range(begin, begin + 3, mid_range)
723     assert(test(ShortString_Begin_MidSizedCut_MidRange));
724     // short_str.replace_with_range(begin, begin + 3, long_range)
725     assert(test(ShortString_Begin_MidSizedCut_LongRange));
726     // short_str.replace_with_range(begin, end, empty_range)
727     assert(test(ShortString_Begin_CutToEnd_EmptyRange));
728     // short_str.replace_with_range(begin, end, one_element_range)
729     assert(test(ShortString_Begin_CutToEnd_OneElementRange));
730     // short_str.replace_with_range(begin, end, mid_range)
731     assert(test(ShortString_Begin_CutToEnd_MidRange));
732     // short_str.replace_with_range(begin, end, long_range)
733     assert(test(ShortString_Begin_CutToEnd_LongRange));
734 
735     // Replace in the middle.
736 
737     // short_str.replace_with_range(mid, mid, empty_range)
738     assert(test(ShortString_Mid_EmptyCut_EmptyRange));
739     // short_str.replace_with_range(mid, mid, one_element_range)
740     assert(test(ShortString_Mid_EmptyCut_OneElementRange));
741     // short_str.replace_with_range(mid, mid, mid_range)
742     assert(test(ShortString_Mid_EmptyCut_MidRange));
743     // short_str.replace_with_range(mid, mid, long_range)
744     assert(test(ShortString_Mid_EmptyCut_LongRange));
745     // short_str.replace_with_range(mid, mid + 1, empty_range)
746     assert(test(ShortString_Mid_OneElementCut_EmptyRange));
747     // short_str.replace_with_range(mid, mid + 1, one_element_range)
748     assert(test(ShortString_Mid_OneElementCut_OneElementRange));
749     // short_str.replace_with_range(mid, mid + 1, mid_range)
750     assert(test(ShortString_Mid_OneElementCut_MidRange));
751     // short_str.replace_with_range(mid, mid + 1, long_range)
752     assert(test(ShortString_Mid_OneElementCut_LongRange));
753     // short_str.replace_with_range(mid, mid + 3, empty_range)
754     assert(test(ShortString_Mid_MidSizedCut_EmptyRange));
755     // short_str.replace_with_range(mid, mid + 3, one_element_range)
756     assert(test(ShortString_Mid_MidSizedCut_OneElementRange));
757     // short_str.replace_with_range(mid, mid + 3, mid_range)
758     assert(test(ShortString_Mid_MidSizedCut_MidRange));
759     // short_str.replace_with_range(mid, mid + 3, long_range)
760     assert(test(ShortString_Mid_MidSizedCut_LongRange));
761     // short_str.replace_with_range(mid, end, empty_range)
762     assert(test(ShortString_Mid_CutToEnd_EmptyRange));
763     // short_str.replace_with_range(mid, end, one_element_range)
764     assert(test(ShortString_Mid_CutToEnd_OneElementRange));
765     // short_str.replace_with_range(mid, end, mid_range)
766     assert(test(ShortString_Mid_CutToEnd_MidRange));
767     // short_str.replace_with_range(mid, end, long_range)
768     assert(test(ShortString_Mid_CutToEnd_LongRange));
769 
770     // Replace at the end.
771 
772     // short_str.replace_with_range(end, end, empty_range)
773     assert(test(ShortString_End_EmptyCut_EmptyRange));
774     // short_str.replace_with_range(end, end, one_element_range)
775     assert(test(ShortString_End_EmptyCut_OneElementRange));
776     // short_str.replace_with_range(end, end, mid_range)
777     assert(test(ShortString_End_EmptyCut_MidRange));
778     // short_str.replace_with_range(end, end, long_range)
779     assert(test(ShortString_End_EmptyCut_LongRange));
780   }
781 
782   { // Long string.
783     // Replace at the beginning.
784 
785     // long_str.replace_with_range(begin, begin, empty_range)
786     assert(test(LongString_Begin_EmptyCut_EmptyRange));
787     // long_str.replace_with_range(begin, begin, one_element_range)
788     assert(test(LongString_Begin_EmptyCut_OneElementRange));
789     // long_str.replace_with_range(begin, begin, mid_range)
790     assert(test(LongString_Begin_EmptyCut_MidRange));
791     // long_str.replace_with_range(begin, begin, long_range)
792     assert(test(LongString_Begin_EmptyCut_LongRange));
793     // long_str.replace_with_range(begin, begin, longer_than_capacity_range)
794     assert(test(LongString_Begin_EmptyCut_LongerThanCapacityRange));
795     // long_str.replace_with_range(begin, begin + 1, empty_range)
796     assert(test(LongString_Begin_OneElementCut_EmptyRange));
797     // long_str.replace_with_range(begin, begin + 1, one_element_range)
798     assert(test(LongString_Begin_OneElementCut_OneElementRange));
799     // long_str.replace_with_range(begin, begin + 1, mid_range)
800     assert(test(LongString_Begin_OneElementCut_MidRange));
801     // long_str.replace_with_range(begin, begin + 1, long_range)
802     assert(test(LongString_Begin_OneElementCut_LongRange));
803     // long_str.replace_with_range(begin, begin + 1, longer_than_capacity_range)
804     assert(test(LongString_Begin_OneElementCut_LongerThanCapacityRange));
805     // long_str.replace_with_range(begin, begin + 3, empty_range)
806     assert(test(LongString_Begin_MidSizedCut_EmptyRange));
807     // long_str.replace_with_range(begin, begin + 3, one_element_range)
808     assert(test(LongString_Begin_MidSizedCut_OneElementRange));
809     // long_str.replace_with_range(begin, begin + 3, mid_range)
810     assert(test(LongString_Begin_MidSizedCut_MidRange));
811     // long_str.replace_with_range(begin, begin + 3, long_range)
812     assert(test(LongString_Begin_MidSizedCut_LongRange));
813     // long_str.replace_with_range(begin, begin + 3, longer_than_capacity_range)
814     assert(test(LongString_Begin_MidSizedCut_LongerThanCapacityRange));
815     // long_str.replace_with_range(begin, end, empty_range)
816     assert(test(LongString_Begin_CutToEnd_EmptyRange));
817     // long_str.replace_with_range(begin, end, one_element_range)
818     assert(test(LongString_Begin_CutToEnd_OneElementRange));
819     // long_str.replace_with_range(begin, end, mid_range)
820     assert(test(LongString_Begin_CutToEnd_MidRange));
821     // long_str.replace_with_range(begin, end, long_range)
822     assert(test(LongString_Begin_CutToEnd_LongRange));
823     // long_str.replace_with_range(begin, end, longer_than_capacity_range)
824     assert(test(LongString_Begin_CutToEnd_LongerThanCapacityRange));
825 
826     // Replace in the middle.
827 
828     // long_str.replace_with_range(mid, mid, empty_range)
829     assert(test(LongString_Mid_EmptyCut_EmptyRange));
830     // long_str.replace_with_range(mid, mid, one_element_range)
831     assert(test(LongString_Mid_EmptyCut_OneElementRange));
832     // long_str.replace_with_range(mid, mid, mid_range)
833     assert(test(LongString_Mid_EmptyCut_MidRange));
834     // long_str.replace_with_range(mid, mid, long_range)
835     assert(test(LongString_Mid_EmptyCut_LongRange));
836     // long_str.replace_with_range(mid, mid, longer_than_capacity_range)
837     assert(test(LongString_Mid_EmptyCut_LongerThanCapacityRange));
838     // long_str.replace_with_range(mid, mid + 1, empty_range)
839     assert(test(LongString_Mid_OneElementCut_EmptyRange));
840     // long_str.replace_with_range(mid, mid + 1, one_element_range)
841     assert(test(LongString_Mid_OneElementCut_OneElementRange));
842     // long_str.replace_with_range(mid, mid + 1, mid_range)
843     assert(test(LongString_Mid_OneElementCut_MidRange));
844     // long_str.replace_with_range(mid, mid + 1, long_range)
845     assert(test(LongString_Mid_OneElementCut_LongRange));
846     // long_str.replace_with_range(mid, mid + 1, longer_than_capacity_range)
847     assert(test(LongString_Mid_OneElementCut_LongerThanCapacityRange));
848     // long_str.replace_with_range(mid, mid + 3, empty_range)
849     assert(test(LongString_Mid_MidSizedCut_EmptyRange));
850     // long_str.replace_with_range(mid, mid + 3, one_element_range)
851     assert(test(LongString_Mid_MidSizedCut_OneElementRange));
852     // long_str.replace_with_range(mid, mid + 3, mid_range)
853     assert(test(LongString_Mid_MidSizedCut_MidRange));
854     // long_str.replace_with_range(mid, mid + 3, long_range)
855     assert(test(LongString_Mid_MidSizedCut_LongRange));
856     // long_str.replace_with_range(mid, mid + 3, longer_than_capacity_range)
857     assert(test(LongString_Mid_MidSizedCut_LongerThanCapacityRange));
858     // long_str.replace_with_range(mid, end, empty_range)
859     assert(test(LongString_Mid_CutToEnd_EmptyRange));
860     // long_str.replace_with_range(mid, end, one_element_range)
861     assert(test(LongString_Mid_CutToEnd_OneElementRange));
862     // long_str.replace_with_range(mid, end, mid_range)
863     assert(test(LongString_Mid_CutToEnd_MidRange));
864     // long_str.replace_with_range(mid, end, long_range)
865     assert(test(LongString_Mid_CutToEnd_LongRange));
866     // long_str.replace_with_range(mid, end, longer_than_capacity_range)
867     assert(test(LongString_Mid_CutToEnd_LongerThanCapacityRange));
868 
869     // Replace at the end.
870 
871     // long_str.replace_with_range(end, end, empty_range)
872     assert(test(LongString_End_EmptyCut_EmptyRange));
873     // long_str.replace_with_range(end, end, one_element_range)
874     assert(test(LongString_End_EmptyCut_OneElementRange));
875     // long_str.replace_with_range(end, end, mid_range)
876     assert(test(LongString_End_EmptyCut_MidRange));
877     // long_str.replace_with_range(end, end, long_range)
878     assert(test(LongString_End_EmptyCut_LongRange));
879     // long_str.replace_with_range(end, end, longer_than_capacity_range)
880     assert(test(LongString_End_EmptyCut_LongerThanCapacityRange));
881   }
882 }
883 
884 constexpr void test_string_replace_with_range_rvalue_range() {
885   // Make sure that the input range can be passed by both an lvalue and an rvalue reference and regardless of constness.
886 
887   { // Lvalue.
888     std::string in = "abc";
889     std::string c  = "123";
890     c.replace_with_range(c.begin(), c.end(), in);
891   }
892 
893   { // Const lvalue.
894     const std::string in = "abc";
895     std::string c        = "123";
896     c.replace_with_range(c.begin(), c.end(), in);
897   }
898 
899   { // Rvalue.
900     std::string in = "abc";
901     std::string c  = "123";
902     c.replace_with_range(c.begin(), c.end(), std::move(in));
903   }
904 
905   { // Const rvalue.
906     const std::string in = "abc";
907     std::string c        = "123";
908     c.replace_with_range(c.begin(), c.end(), std::move(in));
909   }
910 }
911 
912 constexpr bool test_constexpr() {
913   for_all_iterators_and_allocators_constexpr<char, const char*>([]<class Iter, class Sent, class Alloc>() {
914     test_string_replace_with_range<Iter, Sent, Alloc>();
915   });
916   test_string_replace_with_range_rvalue_range();
917 
918   return true;
919 }
920 
921 // Tested cases:
922 // - different kinds of replacements (varying the size of the initial string, the cut point and the cut size, and the
923 //   size of the input range);
924 // - an exception is thrown when allocating new elements.
925 int main(int, char**) {
926   static_assert(test_constraints_replace_with_range());
927 
928   for_all_iterators_and_allocators<char, const char*>([]<class Iter, class Sent, class Alloc>() {
929     test_string_replace_with_range<Iter, Sent, Alloc>();
930   });
931   test_string_replace_with_range_rvalue_range();
932   static_assert(test_constexpr());
933 
934   // Note: `test_string_replace_with_range_exception_safety_throwing_copy` doesn't apply because copying chars cannot
935   // throw.
936   {
937 #if !defined(TEST_HAS_NO_EXCEPTIONS)
938     // Note: the input string must be long enough to prevent SSO, otherwise the allocator won't be used.
939     std::string in(64, 'a');
940 
941     try {
942       ThrowingAllocator<char> alloc;
943 
944       globalMemCounter.reset();
945       std::basic_string<char, std::char_traits<char>, ThrowingAllocator<char>> c(alloc);
946       c.replace_with_range(c.end(), c.end(), in);
947       assert(false); // The function call above should throw.
948 
949     } catch (int) {
950       assert(globalMemCounter.new_called == globalMemCounter.delete_called);
951     }
952 #endif
953   }
954 
955   return 0;
956 }
957