xref: /llvm-project/libcxx/test/std/containers/sequences/insert_range_sequence_containers.h (revision 774295ca1d5ff752cb478b61f22a5b1dbe33074f)
117bbb224Svarconst //===----------------------------------------------------------------------===//
217bbb224Svarconst //
317bbb224Svarconst // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
417bbb224Svarconst // See https://llvm.org/LICENSE.txt for license information.
517bbb224Svarconst // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
617bbb224Svarconst //
717bbb224Svarconst //===----------------------------------------------------------------------===//
817bbb224Svarconst 
917bbb224Svarconst #ifndef SUPPORT_INSERT_RANGE_SEQUENCE_CONTAINERS_H
1017bbb224Svarconst #define SUPPORT_INSERT_RANGE_SEQUENCE_CONTAINERS_H
1117bbb224Svarconst 
1217bbb224Svarconst #include <algorithm>
1317bbb224Svarconst #include <cassert>
1417bbb224Svarconst #include <concepts>
1517bbb224Svarconst #include <cstddef>
1617bbb224Svarconst #include <initializer_list>
1717bbb224Svarconst #include <ranges>
1817bbb224Svarconst #include <type_traits>
1917bbb224Svarconst #include <vector>
2017bbb224Svarconst 
21d0b51657Svarconst #include "../exception_safety_helpers.h"
2217bbb224Svarconst #include "../from_range_helpers.h"
2317bbb224Svarconst #include "../insert_range_helpers.h"
2417bbb224Svarconst #include "MoveOnly.h"
2517bbb224Svarconst #include "almost_satisfies_types.h"
2617bbb224Svarconst #include "count_new.h"
2717bbb224Svarconst #include "min_allocator.h"
2817bbb224Svarconst #include "test_allocator.h"
2917bbb224Svarconst #include "test_iterators.h"
3017bbb224Svarconst #include "test_macros.h"
3117bbb224Svarconst #include "type_algorithms.h"
3217bbb224Svarconst 
3317bbb224Svarconst template <class Container, class Range>
requires(Container & c,Range && range)3417bbb224Svarconst concept HasInsertRange = requires (Container& c, Range&& range) {
3517bbb224Svarconst   c.insert_range(c.end(), range);
3617bbb224Svarconst };
3717bbb224Svarconst 
3817bbb224Svarconst template <template <class...> class Container, class T, class U>
test_constraints_insert_range()3917bbb224Svarconst constexpr bool test_constraints_insert_range() {
4017bbb224Svarconst   // Input range with the same value type.
4117bbb224Svarconst   static_assert(HasInsertRange<Container<T>, InputRange<T>>);
4217bbb224Svarconst   // Input range with a convertible value type.
4317bbb224Svarconst   static_assert(HasInsertRange<Container<T>, InputRange<U>>);
4417bbb224Svarconst   // Input range with a non-convertible value type.
4517bbb224Svarconst   static_assert(!HasInsertRange<Container<T>, InputRange<Empty>>);
4617bbb224Svarconst   // Not an input range.
4717bbb224Svarconst   static_assert(!HasInsertRange<Container<T>, InputRangeNotDerivedFrom>);
4817bbb224Svarconst   static_assert(!HasInsertRange<Container<T>, InputRangeNotIndirectlyReadable>);
4917bbb224Svarconst   static_assert(!HasInsertRange<Container<T>, InputRangeNotInputOrOutputIterator>);
5017bbb224Svarconst 
5117bbb224Svarconst   return true;
5217bbb224Svarconst }
5317bbb224Svarconst 
5417bbb224Svarconst template <class Container, class Range>
requires(Container & c,Range && range)5517bbb224Svarconst concept HasAppendRange = requires (Container& c, Range&& range) {
5617bbb224Svarconst   c.append_range(range);
5717bbb224Svarconst };
5817bbb224Svarconst 
5917bbb224Svarconst template <template <class...> class Container, class T, class U>
test_constraints_append_range()6017bbb224Svarconst constexpr bool test_constraints_append_range() {
6117bbb224Svarconst   // Input range with the same value type.
6217bbb224Svarconst   static_assert(HasAppendRange<Container<T>, InputRange<T>>);
6317bbb224Svarconst   // Input range with a convertible value type.
6417bbb224Svarconst   static_assert(HasAppendRange<Container<T>, InputRange<U>>);
6517bbb224Svarconst   // Input range with a non-convertible value type.
6617bbb224Svarconst   static_assert(!HasAppendRange<Container<T>, InputRange<Empty>>);
6717bbb224Svarconst   // Not an input range.
6817bbb224Svarconst   static_assert(!HasAppendRange<Container<T>, InputRangeNotDerivedFrom>);
6917bbb224Svarconst   static_assert(!HasAppendRange<Container<T>, InputRangeNotIndirectlyReadable>);
7017bbb224Svarconst   static_assert(!HasAppendRange<Container<T>, InputRangeNotInputOrOutputIterator>);
7117bbb224Svarconst 
7217bbb224Svarconst   return true;
7317bbb224Svarconst }
7417bbb224Svarconst 
7517bbb224Svarconst template <class Container, class Range>
requires(Container & c,Range && range)7617bbb224Svarconst concept HasPrependRange = requires (Container& c, Range&& range) {
7717bbb224Svarconst   c.prepend_range(range);
7817bbb224Svarconst };
7917bbb224Svarconst 
8017bbb224Svarconst template <template <class...> class Container, class T, class U>
test_constraints_prepend_range()8117bbb224Svarconst constexpr bool test_constraints_prepend_range() {
8217bbb224Svarconst   // Input range with the same value type.
8317bbb224Svarconst   static_assert(HasPrependRange<Container<T>, InputRange<T>>);
8417bbb224Svarconst   // Input range with a convertible value type.
8517bbb224Svarconst   static_assert(HasPrependRange<Container<T>, InputRange<U>>);
8617bbb224Svarconst   // Input range with a non-convertible value type.
8717bbb224Svarconst   static_assert(!HasPrependRange<Container<T>, InputRange<Empty>>);
8817bbb224Svarconst   // Not an input range.
8917bbb224Svarconst   static_assert(!HasPrependRange<Container<T>, InputRangeNotDerivedFrom>);
9017bbb224Svarconst   static_assert(!HasPrependRange<Container<T>, InputRangeNotIndirectlyReadable>);
9117bbb224Svarconst   static_assert(!HasPrependRange<Container<T>, InputRangeNotInputOrOutputIterator>);
9217bbb224Svarconst 
9317bbb224Svarconst   return true;
9417bbb224Svarconst }
9517bbb224Svarconst 
9617bbb224Svarconst template <class Container, class Range>
requires(Container & c,Range && range)9717bbb224Svarconst concept HasAssignRange = requires (Container& c, Range&& range) {
9817bbb224Svarconst   c.assign_range(range);
9917bbb224Svarconst };
10017bbb224Svarconst 
10117bbb224Svarconst template <template <class...> class Container, class T, class U>
test_constraints_assign_range()10217bbb224Svarconst constexpr bool test_constraints_assign_range() {
10317bbb224Svarconst   // Input range with the same value type.
10417bbb224Svarconst   static_assert(HasAssignRange<Container<T>, InputRange<T>>);
10517bbb224Svarconst   // Input range with a convertible value type.
10617bbb224Svarconst   static_assert(HasAssignRange<Container<T>, InputRange<U>>);
10717bbb224Svarconst   // Input range with a non-convertible value type.
10817bbb224Svarconst   static_assert(!HasAssignRange<Container<T>, InputRange<Empty>>);
10917bbb224Svarconst   // Not an input range.
11017bbb224Svarconst   static_assert(!HasAssignRange<Container<T>, InputRangeNotDerivedFrom>);
11117bbb224Svarconst   static_assert(!HasAssignRange<Container<T>, InputRangeNotIndirectlyReadable>);
11217bbb224Svarconst   static_assert(!HasAssignRange<Container<T>, InputRangeNotInputOrOutputIterator>);
11317bbb224Svarconst 
11417bbb224Svarconst   return true;
11517bbb224Svarconst }
11617bbb224Svarconst 
11717bbb224Svarconst // Empty container.
11817bbb224Svarconst 
11917bbb224Svarconst template <class T>
12017bbb224Svarconst TestCase<T> constexpr EmptyContainer_EmptyRange {
12117bbb224Svarconst   .initial = {}, .index = 0, .input = {}, .expected = {}
12217bbb224Svarconst };
12317bbb224Svarconst // Note: specializations for `bool` still use `vector<int>` for inputs. This is to avoid dealing with `vector<bool>` and
12417bbb224Svarconst // its iterators over proxy types.
12517bbb224Svarconst template <> constexpr TestCase<int> EmptyContainer_EmptyRange<bool> {
12617bbb224Svarconst   .initial = {}, .index = 0, .input = {}, .expected = {}
12717bbb224Svarconst };
12817bbb224Svarconst 
12917bbb224Svarconst template <class T> constexpr TestCase<T> EmptyContainer_OneElementRange;
13017bbb224Svarconst template <> constexpr TestCase<int> EmptyContainer_OneElementRange<int> {
13117bbb224Svarconst   .initial = {}, .index = 0, .input = {5}, .expected = {5}
13217bbb224Svarconst };
13317bbb224Svarconst template <> constexpr TestCase<char> EmptyContainer_OneElementRange<char> {
13417bbb224Svarconst   .initial = {}, .index = 0, .input = "a", .expected = "a"
13517bbb224Svarconst };
13617bbb224Svarconst template <> constexpr TestCase<int> EmptyContainer_OneElementRange<bool> {
13717bbb224Svarconst   .initial = {}, .index = 0, .input = {true}, .expected = {true}
13817bbb224Svarconst };
13917bbb224Svarconst 
14017bbb224Svarconst template <class T> constexpr TestCase<T> EmptyContainer_MidRange;
14117bbb224Svarconst template <> constexpr TestCase<int> EmptyContainer_MidRange<int> {
14217bbb224Svarconst   .initial = {}, .index = 0, .input = {5, 3, 1, 7, 9}, .expected = {5, 3, 1, 7, 9}
14317bbb224Svarconst };
14417bbb224Svarconst template <> constexpr TestCase<char> EmptyContainer_MidRange<char> {
14517bbb224Svarconst   .initial = {}, .index = 0, .input = "aeiou", .expected = "aeiou"
14617bbb224Svarconst };
14717bbb224Svarconst template <> constexpr TestCase<int> EmptyContainer_MidRange<bool> {
14817bbb224Svarconst   .initial = {}, .index = 0, .input = {1, 1, 0, 1, 1}, .expected = {1, 1, 0, 1, 1}
14917bbb224Svarconst };
15017bbb224Svarconst 
15117bbb224Svarconst // One-element container.
15217bbb224Svarconst 
15317bbb224Svarconst template <class T> constexpr TestCase<T> OneElementContainer_Begin_EmptyRange;
15417bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_Begin_EmptyRange<int> {
15517bbb224Svarconst   .initial = {3}, .index = 0, .input = {}, .expected = {3}
15617bbb224Svarconst };
15717bbb224Svarconst template <> constexpr TestCase<char> OneElementContainer_Begin_EmptyRange<char> {
15817bbb224Svarconst   .initial = "B", .index = 0, .input = {}, .expected = "B"
15917bbb224Svarconst };
16017bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_Begin_EmptyRange<bool> {
16117bbb224Svarconst   .initial = {0}, .index = 0, .input = {}, .expected = {0}
16217bbb224Svarconst };
16317bbb224Svarconst 
16417bbb224Svarconst template <class T> constexpr TestCase<T> OneElementContainer_End_EmptyRange;
16517bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_End_EmptyRange<int> {
16617bbb224Svarconst   .initial = {3}, .index = 1, .input = {}, .expected = {3}
16717bbb224Svarconst };
16817bbb224Svarconst template <> constexpr TestCase<char> OneElementContainer_End_EmptyRange<char> {
16917bbb224Svarconst   .initial = "B", .index = 1, .input = {}, .expected = "B"
17017bbb224Svarconst };
17117bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_End_EmptyRange<bool> {
17217bbb224Svarconst   .initial = {0}, .index = 1, .input = {}, .expected = {0}
17317bbb224Svarconst };
17417bbb224Svarconst 
17517bbb224Svarconst template <class T> constexpr TestCase<T> OneElementContainer_Begin_OneElementRange;
17617bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_Begin_OneElementRange<int> {
17717bbb224Svarconst   .initial = {3}, .index = 0, .input = {-5}, .expected = {-5, 3}
17817bbb224Svarconst };
17917bbb224Svarconst template <> constexpr TestCase<char> OneElementContainer_Begin_OneElementRange<char> {
18017bbb224Svarconst   .initial = "B", .index = 0, .input = "a", .expected = "aB"
18117bbb224Svarconst };
18217bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_Begin_OneElementRange<bool> {
18317bbb224Svarconst   .initial = {0}, .index = 0, .input = {1}, .expected = {1, 0}
18417bbb224Svarconst };
18517bbb224Svarconst 
18617bbb224Svarconst template <class T> constexpr TestCase<T> OneElementContainer_End_OneElementRange;
18717bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_End_OneElementRange<int> {
18817bbb224Svarconst   .initial = {3}, .index = 1, .input = {-5}, .expected = {3, -5}
18917bbb224Svarconst };
19017bbb224Svarconst template <> constexpr TestCase<char> OneElementContainer_End_OneElementRange<char> {
19117bbb224Svarconst   .initial = "B", .index = 1, .input = "a", .expected = "Ba"
19217bbb224Svarconst };
19317bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_End_OneElementRange<bool> {
19417bbb224Svarconst   .initial = {0}, .index = 1, .input = {1}, .expected = {0, 1}
19517bbb224Svarconst };
19617bbb224Svarconst 
19717bbb224Svarconst template <class T> constexpr TestCase<T> OneElementContainer_Begin_MidRange;
19817bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_Begin_MidRange<int> {
19917bbb224Svarconst   .initial = {3}, .index = 0, .input = {-5, -3, -1, -7, -9}, .expected = {-5, -3, -1, -7, -9, 3}
20017bbb224Svarconst };
20117bbb224Svarconst template <> constexpr TestCase<char> OneElementContainer_Begin_MidRange<char> {
20217bbb224Svarconst   .initial = "B", .index = 0, .input = "aeiou", .expected = "aeiouB"
20317bbb224Svarconst };
20417bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_Begin_MidRange<bool> {
20517bbb224Svarconst   .initial = {0}, .index = 0, .input = {1, 1, 0, 1, 1}, .expected = {1, 1, 0, 1, 1, 0}
20617bbb224Svarconst };
20717bbb224Svarconst 
20817bbb224Svarconst template <class T> constexpr TestCase<T> OneElementContainer_End_MidRange;
20917bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_End_MidRange<int> {
21017bbb224Svarconst   .initial = {3}, .index = 1, .input = {-5, -3, -1, -7, -9}, .expected = {3, -5, -3, -1, -7, -9}
21117bbb224Svarconst };
21217bbb224Svarconst template <> constexpr TestCase<char> OneElementContainer_End_MidRange<char> {
21317bbb224Svarconst   .initial = "B", .index = 1, .input = "aeiou", .expected = "Baeiou"
21417bbb224Svarconst };
21517bbb224Svarconst template <> constexpr TestCase<int> OneElementContainer_End_MidRange<bool> {
21617bbb224Svarconst   .initial = {0}, .index = 1, .input = {1, 1, 0, 1, 1}, .expected = {0, 1, 1, 0, 1, 1}
21717bbb224Svarconst };
21817bbb224Svarconst 
21917bbb224Svarconst // Full container / empty range.
22017bbb224Svarconst 
22117bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Begin_EmptyRange;
22217bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_EmptyRange<int> {
22317bbb224Svarconst   .initial = {11, 29, 35, 14, 84}, .index = 0, .input = {}, .expected = {11, 29, 35, 14, 84}
22417bbb224Svarconst };
22517bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Begin_EmptyRange<char> {
22617bbb224Svarconst   .initial = "_BCD_", .index = 0, .input = {}, .expected = "_BCD_"
22717bbb224Svarconst };
22817bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_EmptyRange<bool> {
22917bbb224Svarconst   .initial = {0, 0, 1, 0, 0}, .index = 0, .input = {}, .expected = {0, 0, 1, 0, 0}
23017bbb224Svarconst };
23117bbb224Svarconst 
23217bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Mid_EmptyRange;
23317bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_EmptyRange<int> {
23417bbb224Svarconst   .initial = {11, 29, 35, 14, 84}, .index = 2, .input = {}, .expected = {11, 29, 35, 14, 84}
23517bbb224Svarconst };
23617bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Mid_EmptyRange<char> {
23717bbb224Svarconst   .initial = "_BCD_", .index = 2, .input = {}, .expected = "_BCD_"
23817bbb224Svarconst };
23917bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_EmptyRange<bool> {
24017bbb224Svarconst   .initial = {0, 0, 1, 0, 0}, .index = 2, .input = {}, .expected = {0, 0, 1, 0, 0}
24117bbb224Svarconst };
24217bbb224Svarconst 
24317bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_End_EmptyRange;
24417bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_EmptyRange<int> {
24517bbb224Svarconst   .initial = {11, 29, 35, 14, 84}, .index = 5, .input = {}, .expected = {11, 29, 35, 14, 84}
24617bbb224Svarconst };
24717bbb224Svarconst template <> constexpr TestCase<char> FullContainer_End_EmptyRange<char> {
24817bbb224Svarconst   .initial = "_BCD_", .index = 5, .input = {}, .expected = "_BCD_"
24917bbb224Svarconst };
25017bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_EmptyRange<bool> {
25117bbb224Svarconst   .initial = {0, 0, 1, 0, 0}, .index = 5, .input = {}, .expected = {0, 0, 1, 0, 0}
25217bbb224Svarconst };
25317bbb224Svarconst 
25417bbb224Svarconst // Full container / one-element range.
25517bbb224Svarconst 
25617bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Begin_OneElementRange;
25717bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_OneElementRange<int> {
25817bbb224Svarconst   .initial = {11, 29, 35, 14, 84}, .index = 0, .input = {-5}, .expected = {-5, 11, 29, 35, 14, 84}
25917bbb224Svarconst };
26017bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Begin_OneElementRange<char> {
26117bbb224Svarconst   .initial = "_BCD_", .index = 0, .input = "a", .expected = "a_BCD_"
26217bbb224Svarconst };
26317bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_OneElementRange<bool> {
26417bbb224Svarconst   .initial = {0, 0, 1, 0, 0}, .index = 0, .input = {1}, .expected = {1, 0, 0, 1, 0, 0}
26517bbb224Svarconst };
26617bbb224Svarconst 
26717bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Mid_OneElementRange;
26817bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_OneElementRange<int> {
26917bbb224Svarconst   .initial = {11, 29, 35, 14, 84}, .index = 2, .input = {-5}, .expected = {11, 29, -5, 35, 14, 84}
27017bbb224Svarconst };
27117bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Mid_OneElementRange<char> {
27217bbb224Svarconst   .initial = "_BCD_", .index = 2, .input = "a", .expected = "_BaCD_"
27317bbb224Svarconst };
27417bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_OneElementRange<bool> {
27517bbb224Svarconst   .initial = {0, 0, 1, 0, 0}, .index = 2, .input = {1}, .expected = {0, 0, 1, 1, 0, 0}
27617bbb224Svarconst };
27717bbb224Svarconst 
27817bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_End_OneElementRange;
27917bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_OneElementRange<int> {
28017bbb224Svarconst   .initial = {11, 29, 35, 14, 84}, .index = 5, .input = {-5}, .expected = {11, 29, 35, 14, 84, -5}
28117bbb224Svarconst };
28217bbb224Svarconst template <> constexpr TestCase<char> FullContainer_End_OneElementRange<char> {
28317bbb224Svarconst   .initial = "_BCD_", .index = 5, .input = "a", .expected = "_BCD_a"
28417bbb224Svarconst };
28517bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_OneElementRange<bool> {
28617bbb224Svarconst   .initial = {0, 0, 1, 0, 0}, .index = 5, .input = {1}, .expected = {0, 0, 1, 0, 0, 1}
28717bbb224Svarconst };
28817bbb224Svarconst 
28917bbb224Svarconst // Full container / mid-sized range.
29017bbb224Svarconst 
29117bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Begin_MidRange;
29217bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_MidRange<int> {
29317bbb224Svarconst   .initial = {11, 29, 35, 14, 84},
29417bbb224Svarconst   .index = 0,
29517bbb224Svarconst   .input = {-5, -3, -1, -7, -9},
29617bbb224Svarconst   .expected = {-5, -3, -1, -7, -9, 11, 29, 35, 14, 84}
29717bbb224Svarconst };
29817bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Begin_MidRange<char> {
29917bbb224Svarconst   .initial = "_BCD_",
30017bbb224Svarconst   .index = 0,
30117bbb224Svarconst   .input = "aeiou",
30217bbb224Svarconst   .expected = "aeiou_BCD_"
30317bbb224Svarconst };
30417bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_MidRange<bool> {
30517bbb224Svarconst   .initial = {0, 0, 1, 0, 1},
30617bbb224Svarconst   .index = 0,
30717bbb224Svarconst   .input = {1, 1, 0, 1, 1},
30817bbb224Svarconst   .expected = {1, 1, 0, 1, 1, 0, 0, 1, 0, 1}
30917bbb224Svarconst };
31017bbb224Svarconst 
31117bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Mid_MidRange;
31217bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_MidRange<int> {
31317bbb224Svarconst   .initial = {11, 29, 35, 14, 84},
31417bbb224Svarconst   .index = 2,
31517bbb224Svarconst   .input = {-5, -3, -1, -7, -9},
31617bbb224Svarconst   .expected = {11, 29, -5, -3, -1, -7, -9, 35, 14, 84}
31717bbb224Svarconst };
31817bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Mid_MidRange<char> {
31917bbb224Svarconst   .initial = "_BCD_",
32017bbb224Svarconst   .index = 2,
32117bbb224Svarconst   .input = "aeiou",
32217bbb224Svarconst   .expected = "_BaeiouCD_"
32317bbb224Svarconst };
32417bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_MidRange<bool> {
32517bbb224Svarconst   .initial = {0, 0, 1, 0, 1},
32617bbb224Svarconst   .index = 2,
32717bbb224Svarconst   .input = {1, 1, 0, 1, 1},
32817bbb224Svarconst   .expected = {0, 0, 1, 1, 0, 1, 1, 1, 0, 1}
32917bbb224Svarconst };
33017bbb224Svarconst 
33117bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_End_MidRange;
33217bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_MidRange<int> {
33317bbb224Svarconst   .initial = {11, 29, 35, 14, 84},
33417bbb224Svarconst   .index = 5,
33517bbb224Svarconst   .input = {-5, -3, -1, -7, -9},
33617bbb224Svarconst   .expected = {11, 29, 35, 14, 84, -5, -3, -1, -7, -9}
33717bbb224Svarconst };
33817bbb224Svarconst template <> constexpr TestCase<char> FullContainer_End_MidRange<char> {
33917bbb224Svarconst   .initial = "_BCD_",
34017bbb224Svarconst   .index = 5,
34117bbb224Svarconst   .input = "aeiou",
34217bbb224Svarconst   .expected = "_BCD_aeiou"
34317bbb224Svarconst };
34417bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_MidRange<bool> {
34517bbb224Svarconst   .initial = {0, 0, 1, 0, 1},
34617bbb224Svarconst   .index = 5,
34717bbb224Svarconst   .input = {1, 1, 0, 1, 1},
34817bbb224Svarconst   .expected = {0, 0, 1, 0, 1, 1, 1, 0, 1, 1}
34917bbb224Svarconst };
35017bbb224Svarconst 
35117bbb224Svarconst // Full container / long range.
35217bbb224Svarconst 
35317bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Begin_LongRange;
35417bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_LongRange<int> {
35517bbb224Svarconst   .initial = {11, 29, 35, 14, 84},
35617bbb224Svarconst   .index = 0,
35717bbb224Svarconst   .input = {-5, -3, -1, -7, -9, -19, -48, -56, -13, -14, -29, -88, -17, -1, -5, -11, -89, -21, -33, -48},
35817bbb224Svarconst   .expected = {
35917bbb224Svarconst       -5, -3, -1, -7, -9, -19, -48, -56, -13, -14, -29, -88, -17, -1, -5, -11, -89, -21, -33, -48, 11, 29, 35, 14, 84
36017bbb224Svarconst   }
36117bbb224Svarconst };
36217bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Begin_LongRange<char> {
36317bbb224Svarconst   .initial = "_BCD_",
36417bbb224Svarconst   .index = 0,
36517bbb224Svarconst   .input = "aeiouqwxyz5781964203",
36617bbb224Svarconst   .expected = "aeiouqwxyz5781964203_BCD_"
36717bbb224Svarconst };
36817bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Begin_LongRange<bool> {
36917bbb224Svarconst   .initial = {0, 0, 1, 0, 0},
37017bbb224Svarconst   .index = 0,
37117bbb224Svarconst   .input = {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
37217bbb224Svarconst   .expected = {
37317bbb224Svarconst       1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
37417bbb224Svarconst   }
37517bbb224Svarconst };
37617bbb224Svarconst 
37717bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_Mid_LongRange;
37817bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_LongRange<int> {
37917bbb224Svarconst   .initial = {11, 29, 35, 14, 84},
38017bbb224Svarconst   .index = 2,
38117bbb224Svarconst   .input = {-5, -3, -1, -7, -9, -19, -48, -56, -13, -14, -29, -88, -17, -1, -5, -11, -89, -21, -33, -48},
38217bbb224Svarconst   .expected = {
38317bbb224Svarconst       11, 29, -5, -3, -1, -7, -9, -19, -48, -56, -13, -14, -29, -88, -17, -1, -5, -11, -89, -21, -33, -48, 35, 14, 84
38417bbb224Svarconst   }
38517bbb224Svarconst };
38617bbb224Svarconst template <> constexpr TestCase<char> FullContainer_Mid_LongRange<char> {
38717bbb224Svarconst   .initial = "_BCD_",
38817bbb224Svarconst   .index = 2,
38917bbb224Svarconst   .input = "aeiouqwxyz5781964203",
39017bbb224Svarconst   .expected = "_Baeiouqwxyz5781964203CD_"
39117bbb224Svarconst };
39217bbb224Svarconst template <> constexpr TestCase<int> FullContainer_Mid_LongRange<bool> {
39317bbb224Svarconst   .initial = {0, 0, 1, 0, 0},
39417bbb224Svarconst   .index = 2,
39517bbb224Svarconst   .input = {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
39617bbb224Svarconst   .expected = {
39717bbb224Svarconst       0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0
39817bbb224Svarconst   }
39917bbb224Svarconst };
40017bbb224Svarconst 
40117bbb224Svarconst template <class T> constexpr TestCase<T> FullContainer_End_LongRange;
40217bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_LongRange<int> {
40317bbb224Svarconst   .initial = {11, 29, 35, 14, 84},
40417bbb224Svarconst   .index = 5,
40517bbb224Svarconst   .input = {-5, -3, -1, -7, -9, -19, -48, -56, -13, -14, -29, -88, -17, -1, -5, -11, -89, -21, -33, -48},
40617bbb224Svarconst   .expected = {
40717bbb224Svarconst       11, 29, 35, 14, 84, -5, -3, -1, -7, -9, -19, -48, -56, -13, -14, -29, -88, -17, -1, -5, -11, -89, -21, -33, -48
40817bbb224Svarconst   }
40917bbb224Svarconst };
41017bbb224Svarconst template <> constexpr TestCase<char> FullContainer_End_LongRange<char> {
41117bbb224Svarconst   .initial = "_BCD_",
41217bbb224Svarconst   .index = 5,
41317bbb224Svarconst   .input = "aeiouqwxyz5781964203",
41417bbb224Svarconst   .expected = "_BCD_aeiouqwxyz5781964203"
41517bbb224Svarconst };
41617bbb224Svarconst template <> constexpr TestCase<int> FullContainer_End_LongRange<bool> {
41717bbb224Svarconst   .initial = {0, 0, 1, 0, 1},
41817bbb224Svarconst   .index = 5,
41917bbb224Svarconst   .input = {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
42017bbb224Svarconst   .expected = {
42117bbb224Svarconst       0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
42217bbb224Svarconst   }
42317bbb224Svarconst };
42417bbb224Svarconst 
42517bbb224Svarconst // Sequence containers tests.
42617bbb224Svarconst 
42717bbb224Svarconst template <class Container, class Iter, class Sent, class Validate>
test_sequence_insert_range(Validate validate)42817bbb224Svarconst constexpr void test_sequence_insert_range(Validate validate) {
42917bbb224Svarconst   using T = typename Container::value_type;
430*774295caSStephan T. Lavavej   using D      = typename Container::difference_type;
431*774295caSStephan T. Lavavej   auto get_pos = [](auto& c, auto& test_case) { return std::ranges::next(c.begin(), static_cast<D>(test_case.index)); };
43217bbb224Svarconst 
43317bbb224Svarconst   auto test = [&](auto& test_case) {
43417bbb224Svarconst     Container c(test_case.initial.begin(), test_case.initial.end());
43517bbb224Svarconst     auto in = wrap_input<Iter, Sent>(test_case.input);
43617bbb224Svarconst     auto pos = get_pos(c, test_case);
43717bbb224Svarconst 
43817bbb224Svarconst     auto result = c.insert_range(pos, in);
43917bbb224Svarconst     assert(result == get_pos(c, test_case));
44017bbb224Svarconst     validate(c);
44117bbb224Svarconst     return std::ranges::equal(c, test_case.expected);
44217bbb224Svarconst   };
44317bbb224Svarconst 
44417bbb224Svarconst   { // Empty container.
44517bbb224Svarconst     // empty_c.insert_range(end, empty_range)
44617bbb224Svarconst     assert(test(EmptyContainer_EmptyRange<T>));
44717bbb224Svarconst     // empty_c.insert_range(end, one_element_range)
44817bbb224Svarconst     assert(test(EmptyContainer_OneElementRange<T>));
44917bbb224Svarconst     // empty_c.insert_range(end, mid_range)
45017bbb224Svarconst     assert(test(EmptyContainer_MidRange<T>));
45117bbb224Svarconst   }
45217bbb224Svarconst 
45317bbb224Svarconst   { // One-element container.
45417bbb224Svarconst     // one_element_c.insert_range(begin, empty_range)
45517bbb224Svarconst     assert(test(OneElementContainer_Begin_EmptyRange<T>));
45617bbb224Svarconst     // one_element_c.insert_range(end, empty_range)
45717bbb224Svarconst     assert(test(OneElementContainer_End_EmptyRange<T>));
45817bbb224Svarconst     // one_element_c.insert_range(begin, one_element_range)
45917bbb224Svarconst     assert(test(OneElementContainer_Begin_OneElementRange<T>));
46017bbb224Svarconst     // one_element_c.insert_range(end, one_element_range)
46117bbb224Svarconst     assert(test(OneElementContainer_End_OneElementRange<T>));
46217bbb224Svarconst     // one_element_c.insert_range(begin, mid_range)
46317bbb224Svarconst     assert(test(OneElementContainer_Begin_MidRange<T>));
46417bbb224Svarconst     // one_element_c.insert_range(end, mid_range)
46517bbb224Svarconst     assert(test(OneElementContainer_End_MidRange<T>));
46617bbb224Svarconst   }
46717bbb224Svarconst 
46817bbb224Svarconst   { // Full container.
46917bbb224Svarconst     // full_container.insert_range(begin, empty_range)
47017bbb224Svarconst     assert(test(FullContainer_Begin_EmptyRange<T>));
47117bbb224Svarconst     // full_container.insert_range(mid, empty_range)
47217bbb224Svarconst     assert(test(FullContainer_Mid_EmptyRange<T>));
47317bbb224Svarconst     // full_container.insert_range(end, empty_range)
47417bbb224Svarconst     assert(test(FullContainer_End_EmptyRange<T>));
47517bbb224Svarconst     // full_container.insert_range(begin, one_element_range)
47617bbb224Svarconst     assert(test(FullContainer_Begin_OneElementRange<T>));
47717bbb224Svarconst     // full_container.insert_range(end, one_element_range)
47817bbb224Svarconst     assert(test(FullContainer_Mid_OneElementRange<T>));
47917bbb224Svarconst     // full_container.insert_range(end, one_element_range)
48017bbb224Svarconst     assert(test(FullContainer_End_OneElementRange<T>));
48117bbb224Svarconst     // full_container.insert_range(begin, mid_range)
48217bbb224Svarconst     assert(test(FullContainer_Begin_MidRange<T>));
48317bbb224Svarconst     // full_container.insert_range(mid, mid_range)
48417bbb224Svarconst     assert(test(FullContainer_Mid_MidRange<T>));
48517bbb224Svarconst     // full_container.insert_range(end, mid_range)
48617bbb224Svarconst     assert(test(FullContainer_End_MidRange<T>));
48717bbb224Svarconst     // full_container.insert_range(begin, long_range)
48817bbb224Svarconst     assert(test(FullContainer_Begin_LongRange<T>));
48917bbb224Svarconst     // full_container.insert_range(mid, long_range)
49017bbb224Svarconst     assert(test(FullContainer_Mid_LongRange<T>));
49117bbb224Svarconst     // full_container.insert_range(end, long_range)
49217bbb224Svarconst     assert(test(FullContainer_End_LongRange<T>));
49317bbb224Svarconst   }
49417bbb224Svarconst }
49517bbb224Svarconst 
49617bbb224Svarconst template <class Container, class Iter, class Sent, class Validate>
test_sequence_prepend_range(Validate validate)49717bbb224Svarconst constexpr void test_sequence_prepend_range(Validate validate) {
49817bbb224Svarconst   using T = typename Container::value_type;
49917bbb224Svarconst 
50017bbb224Svarconst   auto test = [&](auto& test_case) {
50117bbb224Svarconst     Container c(test_case.initial.begin(), test_case.initial.end());
50217bbb224Svarconst     auto in = wrap_input<Iter, Sent>(test_case.input);
50317bbb224Svarconst 
50417bbb224Svarconst     c.prepend_range(in);
50517bbb224Svarconst     validate(c);
50617bbb224Svarconst     return std::ranges::equal(c, test_case.expected);
50717bbb224Svarconst   };
50817bbb224Svarconst 
50917bbb224Svarconst   { // Empty container.
51017bbb224Svarconst     // empty_c.prepend_range(empty_range)
51117bbb224Svarconst     assert(test(EmptyContainer_EmptyRange<T>));
51217bbb224Svarconst     // empty_c.prepend_range(one_element_range)
51317bbb224Svarconst     assert(test(EmptyContainer_OneElementRange<T>));
51417bbb224Svarconst     // empty_c.prepend_range(mid_range)
51517bbb224Svarconst     assert(test(EmptyContainer_MidRange<T>));
51617bbb224Svarconst   }
51717bbb224Svarconst 
51817bbb224Svarconst   { // One-element container.
51917bbb224Svarconst     // one_element_c.prepend_range(empty_range)
52017bbb224Svarconst     assert(test(OneElementContainer_Begin_EmptyRange<T>));
52117bbb224Svarconst     // one_element_c.prepend_range(one_element_range)
52217bbb224Svarconst     assert(test(OneElementContainer_Begin_OneElementRange<T>));
52317bbb224Svarconst     // one_element_c.prepend_range(mid_range)
52417bbb224Svarconst     assert(test(OneElementContainer_Begin_MidRange<T>));
52517bbb224Svarconst   }
52617bbb224Svarconst 
52717bbb224Svarconst   { // Full container.
52817bbb224Svarconst     // full_container.prepend_range(empty_range)
52917bbb224Svarconst     assert(test(FullContainer_Begin_EmptyRange<T>));
53017bbb224Svarconst     // full_container.prepend_range(one_element_range)
53117bbb224Svarconst     assert(test(FullContainer_Begin_OneElementRange<T>));
53217bbb224Svarconst     // full_container.prepend_range(mid_range)
53317bbb224Svarconst     assert(test(FullContainer_Begin_MidRange<T>));
53417bbb224Svarconst     // full_container.prepend_range(long_range)
53517bbb224Svarconst     assert(test(FullContainer_Begin_LongRange<T>));
53617bbb224Svarconst   }
53717bbb224Svarconst }
53817bbb224Svarconst 
53917bbb224Svarconst template <class Container, class Iter, class Sent, class Validate>
test_sequence_append_range(Validate validate)54017bbb224Svarconst constexpr void test_sequence_append_range(Validate validate) {
54117bbb224Svarconst   using T = typename Container::value_type;
54217bbb224Svarconst 
54317bbb224Svarconst   auto test = [&](auto& test_case) {
54417bbb224Svarconst     Container c(test_case.initial.begin(), test_case.initial.end());
54517bbb224Svarconst     auto in = wrap_input<Iter, Sent>(test_case.input);
54617bbb224Svarconst 
54717bbb224Svarconst     c.append_range(in);
54817bbb224Svarconst     validate(c);
54917bbb224Svarconst     return std::ranges::equal(c, test_case.expected);
55017bbb224Svarconst   };
55117bbb224Svarconst 
55217bbb224Svarconst   { // Empty container.
55317bbb224Svarconst     // empty_c.append_range(empty_range)
55417bbb224Svarconst     assert(test(EmptyContainer_EmptyRange<T>));
55517bbb224Svarconst     // empty_c.append_range(one_element_range)
55617bbb224Svarconst     assert(test(EmptyContainer_OneElementRange<T>));
55717bbb224Svarconst     // empty_c.append_range(mid_range)
55817bbb224Svarconst     assert(test(EmptyContainer_MidRange<T>));
55917bbb224Svarconst   }
56017bbb224Svarconst 
56117bbb224Svarconst   { // One-element container.
56217bbb224Svarconst     // one_element_c.append_range(empty_range)
56317bbb224Svarconst     assert(test(OneElementContainer_End_EmptyRange<T>));
56417bbb224Svarconst     // one_element_c.append_range(one_element_range)
56517bbb224Svarconst     assert(test(OneElementContainer_End_OneElementRange<T>));
56617bbb224Svarconst     // one_element_c.append_range(mid_range)
56717bbb224Svarconst     assert(test(OneElementContainer_End_MidRange<T>));
56817bbb224Svarconst   }
56917bbb224Svarconst 
57017bbb224Svarconst   { // Full container.
57117bbb224Svarconst     // full_container.append_range(empty_range)
57217bbb224Svarconst     assert(test(FullContainer_End_EmptyRange<T>));
57317bbb224Svarconst     // full_container.append_range(one_element_range)
57417bbb224Svarconst     assert(test(FullContainer_End_OneElementRange<T>));
57517bbb224Svarconst     // full_container.append_range(mid_range)
57617bbb224Svarconst     assert(test(FullContainer_End_MidRange<T>));
57717bbb224Svarconst     // full_container.append_range(long_range)
57817bbb224Svarconst     assert(test(FullContainer_End_LongRange<T>));
57917bbb224Svarconst   }
58017bbb224Svarconst }
58117bbb224Svarconst 
58217bbb224Svarconst template <class Container, class Iter, class Sent, class Validate>
test_sequence_assign_range(Validate validate)58317bbb224Svarconst constexpr void test_sequence_assign_range(Validate validate) {
58417bbb224Svarconst   using T = typename Container::value_type;
58517bbb224Svarconst 
58617bbb224Svarconst   auto& initial_empty = EmptyContainer_EmptyRange<T>.initial;
58717bbb224Svarconst   auto& initial_one_element = OneElementContainer_Begin_EmptyRange<T>.initial;
58817bbb224Svarconst   auto& initial_full = FullContainer_Begin_EmptyRange<T>.initial;
58917bbb224Svarconst   auto& input_empty = FullContainer_Begin_EmptyRange<T>.input;
59017bbb224Svarconst   auto& input_one_element = FullContainer_Begin_OneElementRange<T>.input;
59117bbb224Svarconst   auto& input_mid_range = FullContainer_Begin_MidRange<T>.input;
59217bbb224Svarconst   auto& input_long_range = FullContainer_Begin_LongRange<T>.input;
59317bbb224Svarconst 
59417bbb224Svarconst   auto test = [&](auto& initial, auto& input) {
59517bbb224Svarconst     Container c(initial.begin(), initial.end());
59617bbb224Svarconst     auto in = wrap_input<Iter, Sent>(input);
59717bbb224Svarconst 
59817bbb224Svarconst     c.assign_range(in);
59917bbb224Svarconst     validate(c);
60017bbb224Svarconst     return std::ranges::equal(c, input);
60117bbb224Svarconst   };
60217bbb224Svarconst 
60317bbb224Svarconst   { // Empty container.
60417bbb224Svarconst     // empty_container.assign_range(empty_range)
60517bbb224Svarconst     assert(test(initial_empty, input_empty));
60617bbb224Svarconst     // empty_container.assign_range(one_element_range)
60717bbb224Svarconst     assert(test(initial_empty, input_one_element));
60817bbb224Svarconst     // empty_container.assign_range(mid_range)
60917bbb224Svarconst     assert(test(initial_empty, input_mid_range));
61017bbb224Svarconst     // empty_container.assign_range(long_range)
61117bbb224Svarconst     assert(test(initial_empty, input_long_range));
61217bbb224Svarconst   }
61317bbb224Svarconst 
61417bbb224Svarconst   { // One-element container.
61517bbb224Svarconst     // one_element_container.assign_range(empty_range)
61617bbb224Svarconst     assert(test(initial_one_element, input_empty));
61717bbb224Svarconst     // one_element_container.assign_range(one_element_range)
61817bbb224Svarconst     assert(test(initial_one_element, input_one_element));
61917bbb224Svarconst     // one_element_container.assign_range(mid_range)
62017bbb224Svarconst     assert(test(initial_one_element, input_mid_range));
62117bbb224Svarconst     // one_element_container.assign_range(long_range)
62217bbb224Svarconst     assert(test(initial_one_element, input_long_range));
62317bbb224Svarconst   }
62417bbb224Svarconst 
62517bbb224Svarconst   { // Full container.
62617bbb224Svarconst     // full_container.assign_range(empty_range)
62717bbb224Svarconst     assert(test(initial_full, input_empty));
62817bbb224Svarconst     // full_container.assign_range(one_element_range)
62917bbb224Svarconst     assert(test(initial_full, input_one_element));
63017bbb224Svarconst     // full_container.assign_range(mid_range)
63117bbb224Svarconst     assert(test(initial_full, input_mid_range));
63217bbb224Svarconst     // full_container.assign_range(long_range)
63317bbb224Svarconst     assert(test(initial_full, input_long_range));
63417bbb224Svarconst   }
63517bbb224Svarconst }
63617bbb224Svarconst 
63717bbb224Svarconst // Move-only types.
63817bbb224Svarconst 
63917bbb224Svarconst template <template <class ...> class Container>
test_sequence_insert_range_move_only()64017bbb224Svarconst constexpr void test_sequence_insert_range_move_only() {
64117bbb224Svarconst   MoveOnly input[5];
64217bbb224Svarconst   std::ranges::subrange in(std::move_iterator{input}, std::move_iterator{input + 5});
64317bbb224Svarconst 
64417bbb224Svarconst   Container<MoveOnly> c;
64517bbb224Svarconst   c.insert_range(c.end(), in);
64617bbb224Svarconst }
64717bbb224Svarconst 
64817bbb224Svarconst template <template <class ...> class Container>
test_sequence_prepend_range_move_only()64917bbb224Svarconst constexpr void test_sequence_prepend_range_move_only() {
65017bbb224Svarconst   MoveOnly input[5];
65117bbb224Svarconst   std::ranges::subrange in(std::move_iterator{input}, std::move_iterator{input + 5});
65217bbb224Svarconst 
65317bbb224Svarconst   Container<MoveOnly> c;
65417bbb224Svarconst   c.prepend_range(in);
65517bbb224Svarconst }
65617bbb224Svarconst 
65717bbb224Svarconst template <template <class ...> class Container>
test_sequence_append_range_move_only()65817bbb224Svarconst constexpr void test_sequence_append_range_move_only() {
65917bbb224Svarconst   MoveOnly input[5];
66017bbb224Svarconst   std::ranges::subrange in(std::move_iterator{input}, std::move_iterator{input + 5});
66117bbb224Svarconst 
66217bbb224Svarconst   Container<MoveOnly> c;
66317bbb224Svarconst   c.append_range(in);
66417bbb224Svarconst }
66517bbb224Svarconst 
66617bbb224Svarconst template <template <class ...> class Container>
test_sequence_assign_range_move_only()66717bbb224Svarconst constexpr void test_sequence_assign_range_move_only() {
66817bbb224Svarconst   MoveOnly input[5];
66917bbb224Svarconst   std::ranges::subrange in(std::move_iterator{input}, std::move_iterator{input + 5});
67017bbb224Svarconst 
67117bbb224Svarconst   Container<MoveOnly> c;
67217bbb224Svarconst   c.assign_range(in);
67317bbb224Svarconst }
67417bbb224Svarconst 
67517bbb224Svarconst // Exception safety.
67617bbb224Svarconst 
67717bbb224Svarconst template <template <class ...> class Container>
test_insert_range_exception_safety_throwing_copy()67817bbb224Svarconst void test_insert_range_exception_safety_throwing_copy() {
67917bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
680d0b51657Svarconst   constexpr int ThrowOn = 3;
681d0b51657Svarconst   using T = ThrowingCopy<ThrowOn>;
682d0b51657Svarconst   test_exception_safety_throwing_copy<ThrowOn, /*Size=*/5>([](T* from, T* to) {
68317bbb224Svarconst     Container<T> c;
684d0b51657Svarconst     c.insert_range(c.end(), std::ranges::subrange(from, to));
685d0b51657Svarconst   });
68617bbb224Svarconst #endif
68717bbb224Svarconst }
68817bbb224Svarconst 
68917bbb224Svarconst template <template <class ...> class Container, class T>
test_insert_range_exception_safety_throwing_allocator()69017bbb224Svarconst void test_insert_range_exception_safety_throwing_allocator() {
69117bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
69217bbb224Svarconst   T in[] = {0, 1};
69317bbb224Svarconst 
69417bbb224Svarconst   try {
69517bbb224Svarconst     ThrowingAllocator<T> alloc;
69617bbb224Svarconst 
69717bbb224Svarconst     globalMemCounter.reset();
69817bbb224Svarconst     Container<T, ThrowingAllocator<T>> c(alloc);
69917bbb224Svarconst     c.insert_range(c.end(), in);
70017bbb224Svarconst     assert(false); // The function call above should throw.
70117bbb224Svarconst 
70217bbb224Svarconst   } catch (int) {
70317bbb224Svarconst     assert(globalMemCounter.new_called == globalMemCounter.delete_called);
70417bbb224Svarconst   }
70517bbb224Svarconst #endif
70617bbb224Svarconst }
70717bbb224Svarconst 
70817bbb224Svarconst template <template <class ...> class Container>
test_prepend_range_exception_safety_throwing_copy()70917bbb224Svarconst void test_prepend_range_exception_safety_throwing_copy() {
71017bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
711d0b51657Svarconst   constexpr int ThrowOn = 3;
712d0b51657Svarconst   using T = ThrowingCopy<ThrowOn>;
713d0b51657Svarconst   test_exception_safety_throwing_copy<ThrowOn, /*Size=*/5>([](T* from, T* to) {
71417bbb224Svarconst     Container<T> c;
715d0b51657Svarconst     c.prepend_range(std::ranges::subrange(from, to));
716d0b51657Svarconst   });
71717bbb224Svarconst #endif
71817bbb224Svarconst }
71917bbb224Svarconst 
72017bbb224Svarconst template <template <class ...> class Container, class T>
test_prepend_range_exception_safety_throwing_allocator()72117bbb224Svarconst void test_prepend_range_exception_safety_throwing_allocator() {
72217bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
72317bbb224Svarconst   T in[] = {0, 1};
72417bbb224Svarconst 
72517bbb224Svarconst   try {
72617bbb224Svarconst     ThrowingAllocator<T> alloc;
72717bbb224Svarconst 
72817bbb224Svarconst     globalMemCounter.reset();
72917bbb224Svarconst     Container<T, ThrowingAllocator<T>> c(alloc);
73017bbb224Svarconst     c.prepend_range(in);
73117bbb224Svarconst     assert(false); // The function call above should throw.
73217bbb224Svarconst 
73317bbb224Svarconst   } catch (int) {
73417bbb224Svarconst     assert(globalMemCounter.new_called == globalMemCounter.delete_called);
73517bbb224Svarconst   }
73617bbb224Svarconst #endif
73717bbb224Svarconst }
73817bbb224Svarconst 
73917bbb224Svarconst template <template <class ...> class Container>
test_append_range_exception_safety_throwing_copy()74017bbb224Svarconst void test_append_range_exception_safety_throwing_copy() {
74117bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
742d0b51657Svarconst   constexpr int ThrowOn = 3;
743d0b51657Svarconst   using T = ThrowingCopy<ThrowOn>;
744d0b51657Svarconst   test_exception_safety_throwing_copy<ThrowOn, /*Size=*/5>([](T* from, T* to) {
74517bbb224Svarconst     Container<T> c;
746d0b51657Svarconst     c.append_range(std::ranges::subrange(from, to));
747d0b51657Svarconst   });
74817bbb224Svarconst #endif
74917bbb224Svarconst }
75017bbb224Svarconst 
75117bbb224Svarconst template <template <class ...> class Container, class T>
test_append_range_exception_safety_throwing_allocator()75217bbb224Svarconst void test_append_range_exception_safety_throwing_allocator() {
75317bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
75417bbb224Svarconst   T in[] = {0, 1};
75517bbb224Svarconst 
75617bbb224Svarconst   try {
75717bbb224Svarconst     ThrowingAllocator<T> alloc;
75817bbb224Svarconst 
75917bbb224Svarconst     globalMemCounter.reset();
76017bbb224Svarconst     Container<T, ThrowingAllocator<T>> c(alloc);
76117bbb224Svarconst     c.append_range(in);
76217bbb224Svarconst     assert(false); // The function call above should throw.
76317bbb224Svarconst 
76417bbb224Svarconst   } catch (int) {
76517bbb224Svarconst     assert(globalMemCounter.new_called == globalMemCounter.delete_called);
76617bbb224Svarconst   }
76717bbb224Svarconst #endif
76817bbb224Svarconst }
76917bbb224Svarconst 
77017bbb224Svarconst template <template <class ...> class Container>
test_assign_range_exception_safety_throwing_copy()77117bbb224Svarconst void test_assign_range_exception_safety_throwing_copy() {
77217bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
773d0b51657Svarconst   constexpr int ThrowOn = 3;
774d0b51657Svarconst   using T = ThrowingCopy<ThrowOn>;
775d0b51657Svarconst   test_exception_safety_throwing_copy<ThrowOn, /*Size=*/5>([](T* from, T* to) {
77617bbb224Svarconst     Container<T> c;
777d0b51657Svarconst     c.assign_range(std::ranges::subrange(from, to));
778d0b51657Svarconst   });
77917bbb224Svarconst #endif
78017bbb224Svarconst }
78117bbb224Svarconst 
78217bbb224Svarconst template <template <class ...> class Container, class T>
test_assign_range_exception_safety_throwing_allocator()78317bbb224Svarconst void test_assign_range_exception_safety_throwing_allocator() {
78417bbb224Svarconst #if !defined(TEST_HAS_NO_EXCEPTIONS)
78517bbb224Svarconst   T in[] = {0, 1};
78617bbb224Svarconst 
78717bbb224Svarconst   try {
78817bbb224Svarconst     ThrowingAllocator<T> alloc;
78917bbb224Svarconst 
79017bbb224Svarconst     globalMemCounter.reset();
79117bbb224Svarconst     Container<T, ThrowingAllocator<T>> c(alloc);
79217bbb224Svarconst     c.assign_range(in);
79317bbb224Svarconst     assert(false); // The function call above should throw.
79417bbb224Svarconst 
79517bbb224Svarconst   } catch (int) {
79617bbb224Svarconst     assert(globalMemCounter.new_called == globalMemCounter.delete_called);
79717bbb224Svarconst   }
79817bbb224Svarconst #endif
79917bbb224Svarconst }
80017bbb224Svarconst 
80117bbb224Svarconst #endif // SUPPORT_INSERT_RANGE_SEQUENCE_CONTAINERS_H
802