@@ -65,3 +65,121 @@ SCENARIO("range tests", "[core][util][range]")
6565 }
6666 }
6767}
68+
69+ class move_onlyt
70+ {
71+ public:
72+ move_onlyt (move_onlyt &&) = default ;
73+ move_onlyt &operator =(move_onlyt &&) = default ;
74+ move_onlyt (const move_onlyt &) = delete ;
75+ move_onlyt &operator =(const move_onlyt &) = delete ;
76+
77+ explicit move_onlyt (int value) : value{value} {};
78+ int value = 0 ;
79+ };
80+
81+ bool is_odd (const move_onlyt &move_only)
82+ {
83+ return move_only.value % 2 != 0 ;
84+ }
85+
86+ const auto add = [](int left) {
87+ return [=](const move_onlyt &right) { return left + right.value ; };
88+ };
89+
90+ SCENARIO (
91+ " Range tests, with collections of move only typed values." ,
92+ " [core][util][range]" )
93+ {
94+ GIVEN (" A vector of move only typed values." )
95+ {
96+ std::vector<move_onlyt> input;
97+ for (int i = 1 ; i <= 10 ; ++i)
98+ input.emplace_back (i);
99+ THEN (" Values from a range of made from the vector can be moved." )
100+ {
101+ auto input_range = make_range (input);
102+ move_onlyt destination{std::move (*input_range.begin ())};
103+ REQUIRE (destination.value == 1 );
104+ }
105+ THEN (" A range of made from the vector can be filtered." )
106+ {
107+ auto odds_filter = make_range (input).filter (is_odd);
108+ std::size_t total = 0 ;
109+ for (const auto &move_only : odds_filter)
110+ total += 1 ;
111+ REQUIRE (total == 5 );
112+ auto iterator = odds_filter.begin ();
113+ REQUIRE ((iterator++)->value == 1 );
114+ REQUIRE ((iterator++)->value == 3 );
115+ REQUIRE ((iterator++)->value == 5 );
116+ REQUIRE ((iterator++)->value == 7 );
117+ REQUIRE ((iterator++)->value == 9 );
118+ }
119+ THEN (" Values from a filtered range made from the vector can be moved." )
120+ {
121+ std::vector<move_onlyt> odds;
122+ for (move_onlyt &odd : make_range (input).filter (is_odd))
123+ odds.emplace_back (std::move (odd));
124+
125+ REQUIRE (odds.size () == 5 );
126+ REQUIRE (odds[0 ].value == 1 );
127+ REQUIRE (odds[1 ].value == 3 );
128+ REQUIRE (odds[2 ].value == 5 );
129+ REQUIRE (odds[3 ].value == 7 );
130+ REQUIRE (odds[4 ].value == 9 );
131+ }
132+ THEN (" Map can be applied to a range of move only typed values." )
133+ {
134+ std::vector<int > results;
135+ for (int result : make_range (input).map (add (1 )))
136+ results.push_back (result);
137+
138+ const std::vector<int > expected_results{2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 };
139+ REQUIRE (results == expected_results);
140+ }
141+ }
142+ GIVEN (" Two vectors containing move only types values." )
143+ {
144+ std::vector<move_onlyt> input1;
145+ for (int i = 1 ; i <= 3 ; ++i)
146+ input1.emplace_back (i);
147+ std::vector<move_onlyt> input2;
148+ for (int i = 7 ; i <= 9 ; ++i)
149+ input2.emplace_back (i);
150+
151+ THEN (" Values from concatenated ranges made from the vector can be moved." )
152+ {
153+ std::vector<move_onlyt> both_inputs;
154+ for (move_onlyt &input : make_range (input1).concat (make_range (input2)))
155+ both_inputs.emplace_back (std::move (input));
156+
157+ REQUIRE (both_inputs.size () == 6 );
158+ REQUIRE (both_inputs[0 ].value == 1 );
159+ REQUIRE (both_inputs[1 ].value == 2 );
160+ REQUIRE (both_inputs[2 ].value == 3 );
161+ REQUIRE (both_inputs[3 ].value == 7 );
162+ REQUIRE (both_inputs[4 ].value == 8 );
163+ REQUIRE (both_inputs[5 ].value == 9 );
164+ }
165+ }
166+ GIVEN (" A const vector of ints." )
167+ {
168+ const std::vector<int > input{1 , 2 , 3 , 4 , 5 };
169+
170+ THEN (" The vector can be mapped into a range of move-only types" )
171+ {
172+ std::vector<move_onlyt> results;
173+ const auto make_move_only = [](int i) { return move_onlyt{i}; };
174+ for (auto &incremented : make_range (input).map (make_move_only))
175+ results.emplace_back (std::move (incremented));
176+
177+ REQUIRE (results.size () == 5 );
178+ REQUIRE (results[0 ].value == 1 );
179+ REQUIRE (results[1 ].value == 2 );
180+ REQUIRE (results[2 ].value == 3 );
181+ REQUIRE (results[3 ].value == 4 );
182+ REQUIRE (results[4 ].value == 5 );
183+ }
184+ }
185+ }
0 commit comments