1 //===------ MappedIteratorTest.cpp - Unit tests for mapped_iterator -------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/STLExtras.h"
10 #include "gtest/gtest.h"
16 template <typename T
> class MappedIteratorTestBasic
: public testing::Test
{};
19 auto operator()() const {
20 return [](int X
) { return X
+ 1; };
24 struct Plus1LambdaWithCapture
{
27 auto operator()() const {
28 return [=](int X
) { return X
+ One
; };
32 struct Plus1FunctionRef
{
33 static int plus1(int X
) { return X
+ 1; }
35 using FuncT
= int (&)(int);
37 FuncT
operator()() const { return (FuncT
)*plus1
; }
40 struct Plus1FunctionPtr
{
41 static int plus1(int X
) { return X
+ 1; }
43 using FuncT
= int (*)(int);
45 FuncT
operator()() const { return plus1
; }
50 int operator()(int X
) const { return X
+ 1; }
53 auto operator()() const { return Plus1(); }
56 struct Plus1FunctorNotDefaultConstructible
{
61 PlusN(int NArg
) : N(NArg
) {}
63 int operator()(int X
) const { return X
+ N
; }
66 auto operator()() const { return PlusN(1); }
73 Plus1LambdaWithCapture
,
77 Plus1FunctorNotDefaultConstructible
81 TYPED_TEST_SUITE(MappedIteratorTestBasic
, FunctionTypes
, );
83 template <typename T
> using GetFuncT
= decltype(std::declval
<T
>().operator()());
85 TYPED_TEST(MappedIteratorTestBasic
, DefaultConstruct
) {
86 using FuncT
= GetFuncT
<TypeParam
>;
87 using IterT
= mapped_iterator
<typename
std::vector
<int>::iterator
, FuncT
>;
88 TypeParam GetCallable
;
90 auto Func
= GetCallable();
92 constexpr bool DefaultConstruct
=
93 std::is_default_constructible_v
<callable_detail::Callable
<FuncT
>>;
94 EXPECT_TRUE(DefaultConstruct
);
95 EXPECT_TRUE(std::is_default_constructible_v
<IterT
>);
97 if constexpr (std::is_default_constructible_v
<IterT
>) {
103 TYPED_TEST(MappedIteratorTestBasic
, CopyConstruct
) {
104 std::vector
<int> V({0});
106 using FuncT
= GetFuncT
<TypeParam
>;
107 using IterT
= mapped_iterator
<decltype(V
)::iterator
, FuncT
>;
109 EXPECT_TRUE(std::is_copy_constructible_v
<IterT
>);
111 if constexpr (std::is_copy_constructible_v
<IterT
>) {
112 TypeParam GetCallable
;
114 IterT
I1(V
.begin(), GetCallable());
117 EXPECT_EQ(I2
, I1
) << "copy constructed iterator is a different position";
121 TYPED_TEST(MappedIteratorTestBasic
, MoveConstruct
) {
122 std::vector
<int> V({0});
124 using FuncT
= GetFuncT
<TypeParam
>;
125 using IterT
= mapped_iterator
<decltype(V
)::iterator
, FuncT
>;
127 EXPECT_TRUE(std::is_move_constructible_v
<IterT
>);
129 if constexpr (std::is_move_constructible_v
<IterT
>) {
130 TypeParam GetCallable
;
132 IterT
I1(V
.begin(), GetCallable());
133 IterT
I2(V
.begin(), GetCallable());
134 IterT
I3(std::move(I2
));
136 EXPECT_EQ(I3
, I1
) << "move constructed iterator is a different position";
140 TYPED_TEST(MappedIteratorTestBasic
, CopyAssign
) {
141 std::vector
<int> V({0});
143 using FuncT
= GetFuncT
<TypeParam
>;
144 using IterT
= mapped_iterator
<decltype(V
)::iterator
, FuncT
>;
146 EXPECT_TRUE(std::is_copy_assignable_v
<IterT
>);
148 if constexpr (std::is_copy_assignable_v
<IterT
>) {
149 TypeParam GetCallable
;
151 IterT
I1(V
.begin(), GetCallable());
152 IterT
I2(V
.end(), GetCallable());
156 EXPECT_EQ(I2
, I1
) << "copy assigned iterator is a different position";
160 TYPED_TEST(MappedIteratorTestBasic
, MoveAssign
) {
161 std::vector
<int> V({0});
163 using FuncT
= GetFuncT
<TypeParam
>;
164 using IterT
= mapped_iterator
<decltype(V
)::iterator
, FuncT
>;
166 EXPECT_TRUE(std::is_move_assignable_v
<IterT
>);
168 if constexpr (std::is_move_assignable_v
<IterT
>) {
169 TypeParam GetCallable
;
171 IterT
I1(V
.begin(), GetCallable());
172 IterT
I2(V
.begin(), GetCallable());
173 IterT
I3(V
.end(), GetCallable());
177 EXPECT_EQ(I3
, I1
) << "move assigned iterator is a different position";
181 TYPED_TEST(MappedIteratorTestBasic
, GetFunction
) {
182 std::vector
<int> V({0});
184 using FuncT
= GetFuncT
<TypeParam
>;
185 using IterT
= mapped_iterator
<decltype(V
)::iterator
, FuncT
>;
187 TypeParam GetCallable
;
188 IterT
I(V
.begin(), GetCallable());
190 EXPECT_EQ(I
.getFunction()(200), 201);
193 TYPED_TEST(MappedIteratorTestBasic
, GetCurrent
) {
194 std::vector
<int> V({0});
196 using FuncT
= GetFuncT
<TypeParam
>;
197 using IterT
= mapped_iterator
<decltype(V
)::iterator
, FuncT
>;
199 TypeParam GetCallable
;
200 IterT
I(V
.begin(), GetCallable());
202 EXPECT_EQ(I
.getCurrent(), V
.begin());
203 EXPECT_EQ(std::next(I
).getCurrent(), V
.end());
206 TYPED_TEST(MappedIteratorTestBasic
, ApplyFunctionOnDereference
) {
207 std::vector
<int> V({0});
208 TypeParam GetCallable
;
210 auto I
= map_iterator(V
.begin(), GetCallable());
212 EXPECT_EQ(*I
, 1) << "should have applied function in dereference";
215 TEST(MappedIteratorTest
, ApplyFunctionOnArrow
) {
220 std::vector
<int> V({0});
224 auto I
= map_iterator(V
.begin(), [&](int X
) -> S
& { return *(P
+ X
); });
228 EXPECT_EQ(Y
.Z
, 42) << "should have applied function during arrow";
231 TEST(MappedIteratorTest
, FunctionPreservesReferences
) {
232 std::vector
<int> V({1});
233 std::map
<int, int> M({{1, 1}});
235 auto I
= map_iterator(V
.begin(), [&](int X
) -> int & { return M
[X
]; });
238 EXPECT_EQ(M
[1], 42) << "assignment should have modified M";
241 TEST(MappedIteratorTest
, CustomIteratorApplyFunctionOnDereference
) {
242 struct CustomMapIterator
243 : public llvm::mapped_iterator_base
<CustomMapIterator
,
244 std::vector
<int>::iterator
, int> {
247 /// Map the element to the iterator result type.
248 int mapElement(int X
) const { return X
+ 1; }
251 std::vector
<int> V({0});
253 CustomMapIterator
I(V
.begin());
255 EXPECT_EQ(*I
, 1) << "should have applied function in dereference";
258 TEST(MappedIteratorTest
, CustomIteratorApplyFunctionOnArrow
) {
262 struct CustomMapIterator
263 : public llvm::mapped_iterator_base
<CustomMapIterator
,
264 std::vector
<int>::iterator
, S
&> {
265 CustomMapIterator(std::vector
<int>::iterator it
, S
*P
) : BaseT(it
), P(P
) {}
267 /// Map the element to the iterator result type.
268 S
&mapElement(int X
) const { return *(P
+ X
); }
273 std::vector
<int> V({0});
276 CustomMapIterator
I(V
.begin(), &Y
);
280 EXPECT_EQ(Y
.Z
, 42) << "should have applied function during arrow";
283 TEST(MappedIteratorTest
, CustomIteratorFunctionPreservesReferences
) {
284 struct CustomMapIterator
285 : public llvm::mapped_iterator_base
<CustomMapIterator
,
286 std::vector
<int>::iterator
, int &> {
287 CustomMapIterator(std::vector
<int>::iterator it
, std::map
<int, int> &M
)
290 /// Map the element to the iterator result type.
291 int &mapElement(int X
) const { return M
[X
]; }
293 std::map
<int, int> &M
;
295 std::vector
<int> V({1});
296 std::map
<int, int> M({{1, 1}});
298 auto I
= CustomMapIterator(V
.begin(), M
);
301 EXPECT_EQ(M
[1], 42) << "assignment should have modified M";
304 } // anonymous namespace