@@ -52,39 +52,46 @@ struct is_iterable
5252template <class Collection >
5353struct iterate_traits
5454{
55- typedef rxu::decay_t <Collection> collection_type;
56- typedef rxu::decay_t <decltype (std::begin(*(collection_type*)nullptr ))> iterator_type;
57- typedef rxu::value_type_t <std::iterator_traits<iterator_type>> value_type;
55+ // add const due to we don't want to modify original values!
56+ using collection_type = std::add_const_t <rxu::decay_t <Collection>>;
57+ using iterator_type = rxu::decay_t <decltype (std::begin(*(collection_type*)nullptr ))>;
58+ using value_type = rxu::value_type_t <std::iterator_traits<iterator_type>>;
5859};
5960
6061template <class Collection , class Coordination >
6162struct iterate : public source_base <rxu::value_type_t <iterate_traits<Collection>>>
6263{
63- typedef iterate<Collection, Coordination> this_type ;
64- typedef iterate_traits<Collection> traits ;
64+ using this_type = iterate<Collection, Coordination>;
65+ using traits = iterate_traits<Collection>;
6566
66- typedef rxu::decay_t <Coordination> coordination_type ;
67- typedef typename coordination_type::coordinator_type coordinator_type;
67+ using coordination_type = rxu::decay_t <Coordination>;
68+ using coordinator_type = typename coordination_type::coordinator_type;
6869
69- typedef typename traits::collection_type collection_type;
70- typedef typename traits::iterator_type iterator_type;
70+ using collection_type = typename traits::collection_type;
71+ using collection_type_ptr = std::shared_ptr<collection_type>;
72+ using iterator_type = typename traits::iterator_type;
7173
7274 struct iterate_initial_type
7375 {
74- iterate_initial_type (collection_type c, coordination_type cn)
75- : collection(std::move(c))
76- , coordination(std::move(cn))
77- {
78- }
79- collection_type collection;
80- coordination_type coordination;
76+ iterate_initial_type (Collection&& c, coordination_type cn)
77+ : collection_ptr(std::make_shared<collection_type>(std::move(c)))
78+ , coordination(std::move(cn)) { }
79+
80+ iterate_initial_type (const Collection& c, coordination_type cn)
81+ : collection_ptr(std::make_shared<collection_type>(c))
82+ , coordination(std::move(cn)) { }
83+
84+ collection_type_ptr collection_ptr;
85+ coordination_type coordination;
8186 };
8287 iterate_initial_type initial;
8388
84- iterate (collection_type c, coordination_type cn)
85- : initial(std::move(c), std::move(cn))
86- {
87- }
89+ iterate (Collection&& c, coordination_type cn)
90+ : initial(std::move(c), std::move(cn)) { }
91+
92+ iterate (const Collection& c, coordination_type cn)
93+ : initial(c, std::move(cn)) { }
94+
8895 template <class Subscriber >
8996 void on_subscribe (Subscriber o) const {
9097 static_assert (is_subscriber<Subscriber>::value, " subscribe must be passed a subscriber" );
@@ -96,18 +103,19 @@ struct iterate : public source_base<rxu::value_type_t<iterate_traits<Collection>
96103 {
97104 iterate_state_type (const iterate_initial_type& i, output_type o)
98105 : iterate_initial_type(i)
99- , cursor(std::begin(iterate_initial_type::collection ))
100- , end(std::end(iterate_initial_type::collection ))
106+ , cursor(std::begin(* iterate_initial_type::collection_ptr ))
107+ , end(std::end(* iterate_initial_type::collection_ptr ))
101108 , out(std::move(o))
102109 {
103110 }
104111 iterate_state_type (const iterate_state_type& o)
105112 : iterate_initial_type(o)
106- , cursor(std::begin(iterate_initial_type::collection ))
107- , end(std::end(iterate_initial_type::collection ))
113+ , cursor(std::begin(* iterate_initial_type::collection_ptr ))
114+ , end(std::end(* iterate_initial_type::collection_ptr ))
108115 , out(std::move(o.out)) // since lambda capture does not yet support move
109116 {
110117 }
118+
111119 mutable iterator_type cursor;
112120 iterator_type end;
113121 mutable output_type out;
@@ -157,18 +165,18 @@ struct iterate : public source_base<rxu::value_type_t<iterate_traits<Collection>
157165/* ! @copydoc rx-iterate.hpp
158166 */
159167template <class Collection >
160- auto iterate(Collection c)
161- -> observable<rxu::value_type_t <detail::iterate_traits<Collection>>, detail::iterate<Collection, identity_one_worker>> {
162- return observable<rxu::value_type_t <detail::iterate_traits<Collection>>, detail::iterate<Collection, identity_one_worker>>(
163- detail::iterate<Collection, identity_one_worker>(std::move (c), identity_immediate ()));
168+ auto iterate(Collection&& c)
169+ -> observable<rxu::value_type_t <detail::iterate_traits<rxu:: decay_t < Collection>>> , detail::iterate<rxu:: decay_t < Collection> , identity_one_worker>> {
170+ return observable<rxu::value_type_t <detail::iterate_traits<rxu:: decay_t < Collection>>> , detail::iterate<rxu:: decay_t < Collection> , identity_one_worker>>(
171+ detail::iterate<rxu:: decay_t < Collection> , identity_one_worker>(std::forward<Collection> (c), identity_immediate ()));
164172}
165173/* ! @copydoc rx-iterate.hpp
166174 */
167175template <class Collection , class Coordination >
168- auto iterate(Collection c, Coordination cn)
169- -> observable<rxu::value_type_t <detail::iterate_traits<Collection>>, detail::iterate<Collection, Coordination>> {
170- return observable<rxu::value_type_t <detail::iterate_traits<Collection>>, detail::iterate<Collection, Coordination>>(
171- detail::iterate<Collection, Coordination>(std::move (c), std::move (cn)));
176+ auto iterate(Collection&& c, Coordination cn)
177+ -> observable<rxu::value_type_t <detail::iterate_traits<rxu:: decay_t < Collection>>> , detail::iterate<rxu:: decay_t < Collection> , Coordination>> {
178+ return observable<rxu::value_type_t <detail::iterate_traits<rxu:: decay_t < Collection>>> , detail::iterate<rxu:: decay_t < Collection> , Coordination>>(
179+ detail::iterate<rxu:: decay_t < Collection> , Coordination>(std::forward<Collection> (c), std::move (cn)));
172180}
173181
174182/* ! Returns an observable that sends an empty set of values and then completes.
@@ -218,10 +226,10 @@ auto from(Coordination cn)
218226 \note This operator is useful to send separated values. If they are stored as a collection, use observable<void,void>::iterate instead.
219227*/
220228template <class Value0 , class ... ValueN>
221- auto from (Value0 v0, ValueN... vn)
222- -> typename std::enable_if<!is_coordination<Value0>::value,
223- decltype(iterate(*(std::array<Value0, sizeof ...(ValueN) + 1>*)nullptr, identity_immediate()))>::type {
224- std::array<Value0, sizeof ...(ValueN) + 1 > c{{v0, vn ...}};
229+ auto from (Value0&& v0, ValueN&& ... vn)
230+ -> typename std::enable_if<!is_coordination<rxu::decay_t< Value0> >::value,
231+ decltype(iterate(*(std::array<rxu:: decay_t < Value0> , sizeof ...(ValueN) + 1>*)nullptr, identity_immediate()))>::type {
232+ std::array<rxu:: decay_t < Value0> , sizeof ...(ValueN) + 1 > c{{std::forward<Value0>(v0), std::forward<ValueN>(vn) ...}};
225233 return iterate(std::move (c), identity_immediate ());
226234}
227235/* ! Returns an observable that sends each value from its arguments list, on the specified scheduler.
@@ -243,10 +251,10 @@ auto from(Value0 v0, ValueN... vn)
243251 \note This operator is useful to send separated values. If they are stored as a collection, use observable<void,void>::iterate instead.
244252*/
245253template <class Coordination , class Value0 , class ... ValueN>
246- auto from (Coordination cn, Value0 v0, ValueN... vn)
254+ auto from (Coordination cn, Value0&& v0, ValueN&& ... vn)
247255 -> typename std::enable_if<is_coordination<Coordination>::value,
248- decltype(iterate(*(std::array<Value0, sizeof ...(ValueN) + 1>*)nullptr, std::move(cn)))>::type {
249- std::array<Value0, sizeof ...(ValueN) + 1 > c{{v0, vn ...}};
256+ decltype(iterate(*(std::array<rxu:: decay_t < Value0> , sizeof ...(ValueN) + 1>*)nullptr, std::move(cn)))>::type {
257+ std::array<rxu:: decay_t < Value0> , sizeof ...(ValueN) + 1 > c{{std::forward<Value0>(v0), std::forward<ValueN>(vn) ...}};
250258 return iterate(std::move (c), std::move (cn));
251259}
252260
@@ -264,10 +272,10 @@ auto from(Coordination cn, Value0 v0, ValueN... vn)
264272 \snippet output.txt just sample
265273*/
266274template <class Value0 >
267- auto just (Value0 v0)
268- -> typename std::enable_if<!is_coordination<Value0>::value,
269- decltype(iterate(*(std::array<Value0, 1 >*)nullptr, identity_immediate()))>::type {
270- std::array<Value0, 1 > c{{v0 }};
275+ auto just (Value0&& v0)
276+ -> typename std::enable_if<!is_coordination<rxu::decay_t< Value0> >::value,
277+ decltype(iterate(*(std::array<rxu:: decay_t < Value0> , 1 >*)nullptr, identity_immediate()))>::type {
278+ std::array<rxu:: decay_t < Value0> , 1 > c{{std::forward<Value0>(v0) }};
271279 return iterate(std::move (c), identity_immediate ());
272280}
273281/* ! Returns an observable that sends the specified item to observer and then completes, on the specified scheduler.
@@ -285,10 +293,10 @@ auto just(Value0 v0)
285293 \snippet output.txt threaded just sample
286294*/
287295template <class Value0 , class Coordination >
288- auto just (Value0 v0, Coordination cn)
296+ auto just (Value0&& v0, Coordination cn)
289297 -> typename std::enable_if<is_coordination<Coordination>::value,
290- decltype(iterate(*(std::array<Value0, 1 >*)nullptr, std::move(cn)))>::type {
291- std::array<Value0, 1 > c{{v0 }};
298+ decltype(iterate(*(std::array<rxu:: decay_t < Value0> , 1 >*)nullptr, std::move(cn)))>::type {
299+ std::array<rxu:: decay_t < Value0> , 1 > c{{std::forward<Value0>(v0) }};
292300 return iterate(std::move (c), std::move (cn));
293301}
294302
@@ -313,9 +321,9 @@ auto just(Value0 v0, Coordination cn)
313321 \snippet output.txt short start_with sample
314322*/
315323template <class Observable , class Value0 , class ... ValueN>
316- auto start_with (Observable o, Value0 v0, ValueN... vn)
317- -> decltype(from(rxu::value_type_t <Observable>(v0), rxu::value_type_t<Observable>(vn )...).concat(o)) {
318- return from (rxu::value_type_t <Observable>(v0), rxu::value_type_t <Observable>(vn )...).concat (o);
324+ auto start_with (Observable o, Value0&& v0, ValueN&& ... vn)
325+ -> decltype(from(rxu::value_type_t <Observable>(std::forward<Value0>( v0)) , rxu::value_type_t<Observable>(std::forward<ValueN>(vn) )...).concat(o)) {
326+ return from (rxu::value_type_t <Observable>(std::forward<Value0>( v0)) , rxu::value_type_t <Observable>(std::forward<ValueN>(vn) )...).concat (o);
319327}
320328
321329}
0 commit comments