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// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10
11// <flat_set>
12
13// template <class InputIterator>
14// flat_multiset(InputIterator first, InputIterator last, const key_compare& comp = key_compare());
15// template<class InputIterator, class Allocator>
16// flat_multiset(InputIterator first, InputIterator last, const Allocator& a);
17// template<class InputIterator, class Allocator>
18// flat_multiset(InputIterator first, InputIterator last, const key_compare& comp, const Allocator& a);
19
20#include <algorithm>
21#include <deque>
22#include <flat_set>
23#include <functional>
24#include <ranges>
25#include <vector>
26
27#include "min_allocator.h"
28#include "test_allocator.h"
29#include "test_iterators.h"
30#include "test_macros.h"
31#include "../../../test_compare.h"
32
33void test() {
34 {
35 // The constructors in this subclause shall not participate in overload
36 // resolution unless uses_allocator_v<container_type, Alloc> is true.
37
38 using C = test_less<int>;
39 using A1 = test_allocator<int>;
40 using A2 = other_allocator<int>;
41 using V1 = std::vector<int, A1>;
42 using V2 = std::vector<int, A2>;
43 using M1 = std::flat_multiset<int, C, V1>;
44 using M2 = std::flat_multiset<int, C, V2>;
45 using Iter1 = typename M1::iterator;
46 using Iter2 = typename M2::iterator;
47 static_assert(std::is_constructible_v<M1, Iter1, Iter1, const A1&>);
48 static_assert(std::is_constructible_v<M2, Iter2, Iter2, const A2&>);
49 static_assert(!std::is_constructible_v<M1, Iter1, Iter1, const A2&>);
50 static_assert(!std::is_constructible_v<M2, Iter2, Iter2, const A1&>);
51
52 static_assert(std::is_constructible_v<M1, Iter1, Iter1, const C&, const A1&>);
53 static_assert(std::is_constructible_v<M2, Iter2, Iter2, const C&, const A2&>);
54 static_assert(!std::is_constructible_v<M1, Iter1, Iter1, const C&, const A2&>);
55 static_assert(!std::is_constructible_v<M2, Iter2, Iter2, const C&, const A1&>);
56 }
57
58 int ar[] = {1, 1, 1, 2, 2, 3, 2, 3, 3};
59 int expected[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
60 {
61 // flat_multiset(InputIterator , InputIterator)
62 // cpp17_input_iterator
63 using M = std::flat_multiset<int>;
64 auto m = M(cpp17_input_iterator<const int*>(ar), cpp17_input_iterator<const int*>(ar + 9));
65 assert(std::ranges::equal(m, expected));
66
67 // explicit(false)
68 M m2 = {cpp17_input_iterator<const int*>(ar), cpp17_input_iterator<const int*>(ar + 9)};
69 assert(m2 == m);
70 }
71 {
72 // flat_multiset(InputIterator , InputIterator)
73 // greater
74 using M = std::flat_multiset<int, std::greater<int>, std::deque<int, min_allocator<int>>>;
75 auto m = M(cpp17_input_iterator<const int*>(ar), cpp17_input_iterator<const int*>(ar + 9));
76 assert(std::ranges::equal(m, expected | std::views::reverse));
77 }
78 {
79 // flat_multiset(InputIterator , InputIterator)
80 // Test when the operands are of array type (also contiguous iterator type)
81 using M = std::flat_multiset<int, std::greater<int>, std::vector<int, min_allocator<int>>>;
82 auto m = M(ar, ar);
83 assert(m.empty());
84 }
85 {
86 // flat_multiset(InputIterator , InputIterator, const key_compare&)
87 using C = test_less<int>;
88 using M = std::flat_multiset<int, C, std::vector<int>>;
89 auto m = M(ar, ar + 9, C(3));
90 assert(std::ranges::equal(m, expected));
91 assert(m.key_comp() == C(3));
92
93 // explicit(false)
94 M m2 = {ar, ar + 9, C(3)};
95 assert(m2 == m);
96 assert(m2.key_comp() == C(3));
97 }
98 {
99 // flat_multiset(InputIterator , InputIterator, const Allocator&)
100 using A1 = test_allocator<int>;
101 using M = std::flat_multiset<int, std::less<int>, std::vector<int, A1>>;
102 auto m = M(ar, ar + 9, A1(5));
103 assert(std::ranges::equal(m, expected));
104 assert(std::move(m).extract().get_allocator() == A1(5));
105 }
106 {
107 // flat_multiset(InputIterator , InputIterator, const Allocator&)
108 // explicit(false)
109 using A1 = test_allocator<int>;
110 using M = std::flat_multiset<int, std::less<int>, std::vector<int, A1>>;
111 M m = {ar, ar + 9, A1(5)}; // implicit ctor
112 assert(std::ranges::equal(m, expected));
113 assert(std::move(m).extract().get_allocator() == A1(5));
114 }
115 {
116 // flat_multiset(InputIterator , InputIterator, const key_compare&, const Allocator&)
117 using C = test_less<int>;
118 using A1 = test_allocator<int>;
119 using M = std::flat_multiset<int, C, std::vector<int, A1>>;
120 auto m = M(ar, ar + 9, C(3), A1(5));
121 assert(std::ranges::equal(m, expected));
122 assert(m.key_comp() == C(3));
123 assert(std::move(m).extract().get_allocator() == A1(5));
124 }
125 {
126 // flat_multiset(InputIterator , InputIterator, const key_compare&, const Allocator&)
127 // explicit(false)
128 using A1 = test_allocator<int>;
129 using M = std::flat_multiset<int, std::less<int>, std::deque<int, A1>>;
130 M m = {ar, ar + 9, {}, A1(5)}; // implicit ctor
131 assert(std::ranges::equal(m, expected));
132 LIBCPP_ASSERT(std::ranges::equal(m, expected));
133 assert(std::move(m).extract().get_allocator() == A1(5));
134 }
135}
136
137int main(int, char**) {
138 test();
139
140 return 0;
141}
142

source code of libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.cons/iter_iter.pass.cpp