@@ -98,43 +98,45 @@ class sized_iterable_impl : public lazy_view {
98
98
using decayed_iterator = decay_t <I>;
99
99
using decayed_sentinel = decay_t <S>;
100
100
101
- using sentinel_type =
102
- conditional<std::is_same<decayed_iterator, decayed_sentinel>::value, take_iterator<decayed_iterator>, decayed_sentinel>;
103
-
104
- take_iterator<decayed_iterator> _begin;
105
- sentinel_type _end;
106
-
107
- using difference_type = diff_type<decayed_iterator>;
101
+ I _begin;
102
+ S _end;
103
+ std::size_t _size{};
108
104
109
105
public:
110
- using iterator = take_iterator<decayed_iterator>;
106
+ using iterator = take_iterator<decayed_iterator, S >;
111
107
using const_iterator = decayed_iterator;
112
108
using value_type = val_t <decayed_iterator>;
113
- using sentinel = sentinel_type ;
109
+ using sentinel = S ;
114
110
111
+ private:
112
+ using diff_type = typename iterator::difference_type;
113
+
114
+ public:
115
115
constexpr sized_iterable_impl () = default;
116
116
117
117
template <class Cat = typename decayed_iterator::iterator_category, enable_if<is_ra_tag<Cat>::value, int > = 0 >
118
- constexpr sized_iterable_impl (decayed_iterator begin, decayed_iterator end) :
119
- _begin{ std::move (begin), end - begin },
120
- _end{ std::move (end), 0 } {
118
+ constexpr sized_iterable_impl (decayed_iterator begin, S end) :
119
+ _begin{ begin },
120
+ _end{ end },
121
+ _size{ static_cast <std::size_t >(end - begin) } {
121
122
}
122
123
123
124
template <class Cat = typename decayed_iterator::iterator_category, enable_if<!is_ra_tag<Cat>::value, int > = 0 >
124
- constexpr sized_iterable_impl (decayed_iterator begin, decayed_sentinel end) = delete; // Must be random access to get size
125
+ constexpr sized_iterable_impl (decayed_iterator begin,
126
+ decayed_sentinel end) = delete; // Iterator must be random access to get size
125
127
126
- constexpr sized_iterable_impl (decayed_iterator begin, std::size_t size) :
127
- _begin{ std::move (begin), static_cast <difference_type>(size) } {
128
+ template <class Iterable , enable_if<sized<Iterable>::value, int > = 0 >
129
+ constexpr sized_iterable_impl (Iterable&& iterable) :
130
+ _begin{ detail::begin (std::forward<Iterable>(iterable)) },
131
+ _end{ detail::end (iterable) },
132
+ _size{ lz::size (iterable) } {
128
133
}
129
134
130
- template <class It = decayed_iterator>
131
- LZ_NODISCARD constexpr enable_if<std::is_same<It, decayed_sentinel>::value, std::size_t > size () const {
132
- return static_cast <std::size_t >(begin ()._n - end ()._n ) ;
133
- }
135
+ template <class Iterable , enable_if<!sized<Iterable>::value, int > = 0 >
136
+ constexpr sized_iterable_impl (Iterable&& iterable) = delete; // Iterable must be sized
134
137
135
- template <class It = decayed_iterator>
136
- LZ_NODISCARD constexpr enable_if<!std::is_same<It, decayed_sentinel>::value, std::size_t > size () const {
137
- return static_cast <std::size_t >(begin ()._n );
138
+ LZ_NODISCARD constexpr std::size_t size () const noexcept {
139
+ return _size;
138
140
}
139
141
140
142
template <class Rhs >
@@ -170,21 +172,21 @@ class sized_iterable_impl : public lazy_view {
170
172
LZ_MODULE_EXPORT_SCOPE_BEGIN
171
173
172
174
/* *
173
- * @brief A class that can be converted to any container. It is a view over an iterable, meaning it does not own the data. It
175
+ * @brief A class that can be converted to any container. It only contains the iterators and
174
176
* can be used in pipe expressions, converted to a container with `to<Container>()`, used in algorithms, for-each loops, etc...
175
177
* It contains the size of the iterable.
176
- * @tparam It The iterator or iterable type.
177
- * @tparam S The sentinel type, if using an iterator/sentinel pair. Otherwise leave as is .
178
+ * @tparam It The iterator type.
179
+ * @tparam S The sentinel type.
178
180
*/
179
181
template <class It , class S = It>
180
182
using sized_iterable = detail::sized_iterable_impl<It, S>;
181
183
182
184
/* *
183
- * @brief A class that can be converted to any container. It is a view over an iterable, meaning it does not own the data. It
185
+ * @brief A class that can be converted to any container. It only contains the iterators and
184
186
* can be used in pipe expressions, converted to a container with `to<Container>()`, used in algorithms, for-each loops, etc...
185
- * It *may* contain the size of the iterable, depending on the iterator category or if the iterable is sized .
186
- * @tparam It The iterator or iterable type.
187
- * @tparam S The sentinel type, if using an iterator/sentinel pair. Otherwise leave as is .
187
+ * It *may* contain the size of the iterable, depending on the iterator category (needs to be random access) .
188
+ * @tparam It The iterator type.
189
+ * @tparam S The sentinel type.
188
190
*/
189
191
template <class It , class S = It>
190
192
using basic_iterable = detail::basic_iterable_impl<It, S>;
@@ -229,10 +231,11 @@ struct has_push_back<Container, void_t<decltype(0, std::declval<Container>().pus
229
231
: std::true_type {};
230
232
231
233
template <class Container , class = void >
232
- struct custom_copier : std::false_type {} ;
234
+ struct custom_copier_for ;
233
235
234
236
template <class Container >
235
- struct custom_copier <Container, void_t <decltype(0 , std::declval<Container>().push(std::declval<typename Container::value_type>()))>> {
237
+ struct custom_copier_for <Container,
238
+ void_t <decltype(0 , std::declval<Container>().push(std::declval<typename Container::value_type>()))>> {
236
239
template <class Iterable >
237
240
LZ_CONSTEXPR_CXX_20 void copy (Iterable&& iterable, Container& container) const {
238
241
using ref = ref_iterable_t <Iterable>;
@@ -242,7 +245,7 @@ struct custom_copier<Container, void_t<decltype(0, std::declval<Container>().pus
242
245
243
246
// std::array doesnt have push_back, insert, insert_after... etc, so just use copy
244
247
template <class T , std::size_t N>
245
- struct custom_copier <std::array<T, N>> {
248
+ struct custom_copier_for <std::array<T, N>> {
246
249
template <class Iterable >
247
250
LZ_CONSTEXPR_CXX_20 void copy (Iterable&& iterable, std::array<T, N>& container) const {
248
251
lz::copy (std::forward<Iterable>(iterable), container.begin ());
@@ -305,10 +308,9 @@ template<class Iterable, class Container>
305
308
LZ_CONSTEXPR_CXX_20
306
309
enable_if<!has_push_back<Container>::value && !has_insert<Container>::value && !has_insert_after<Container>::value>
307
310
copy_to_container (Iterable&& iterable, Container& container) {
308
- custom_copier <Container>{}.copy (std::forward<Iterable>(iterable), container);
311
+ custom_copier_for <Container>{}.copy (std::forward<Iterable>(iterable), container);
309
312
}
310
313
311
-
312
314
template <class Container >
313
315
struct container_constructor {
314
316
template <class Container , LZ_CONCEPT_ITERABLE Iterable, class ... Args>
@@ -421,8 +423,9 @@ struct iterable_formatter {
421
423
std::string_view fmt{ format };
422
424
std::string_view sep{ separator };
423
425
426
+ const auto empty_fmt_args = std::make_format_args ();
424
427
for (; begin != end; ++begin) {
425
- std::vformat_to (back_inserter, sep, std::make_format_args () );
428
+ std::vformat_to (back_inserter, sep, empty_fmt_args );
426
429
std::vformat_to (back_inserter, fmt, std::make_format_args (*begin));
427
430
}
428
431
@@ -601,9 +604,9 @@ LZ_NODISCARD LZ_CONSTEXPR_CXX_14 Closure to(Args&&... args) {
601
604
* auto list = lz::to<std::list<int>>(vec, std::allocator<int>{}); // { 1, 2, 3, 4, 5 }
602
605
* // etc...
603
606
* ```
604
- * In case you have a custom container, you can specialize `lz::custom_copier ` to copy the elements to your container.
607
+ * In case you have a custom container, you can specialize `lz::custom_copier_for ` to copy the elements to your container.
605
608
* This is useful if you have a custom container that requires a specific way of copying elements. You will need to specialize
606
- * `lz::custom_copier ` for your custom container if all of the following are true:
609
+ * `lz::custom_copier_for ` for your custom container if all of the following are true:
607
610
* - Your custom container does not have a `push_back` method
608
611
* - Your custom container does not have an `insert` method
609
612
* - Your custom container does not have an `insert_after` method (implicitly also requires `before_begin`)
@@ -623,9 +626,9 @@ LZ_NODISCARD LZ_CONSTEXPR_CXX_14 Closure to(Args&&... args) {
623
626
* }
624
627
* };
625
628
*
626
- * // Specialize `lz::custom_copier ` for your custom container
629
+ * // Specialize `lz::custom_copier_for ` for your custom container
627
630
* template<class T>
628
- * struct lz::custom_copier <custom_container<T>> {
631
+ * struct lz::custom_copier_for <custom_container<T>> {
629
632
* template<class Iterable>
630
633
* void copy(Iterable&& iterable, custom_container<T>& container) const {
631
634
* // Copy the contents of the iterable to the container. Container is already reserved
@@ -660,9 +663,9 @@ LZ_NODISCARD constexpr Container to(Iterable&& iterable, Args&&... args) {
660
663
* auto list = lz::to<std::list<int>>(vec, std::allocator<int>{}); // { 1, 2, 3, 4, 5 }
661
664
* // etc...
662
665
* ```
663
- * In case you have a custom container, you can specialize `lz::custom_copier ` to copy the elements to your container.
666
+ * In case you have a custom container, you can specialize `lz::custom_copier_for ` to copy the elements to your container.
664
667
* This is useful if you have a custom container that requires a specific way of copying elements. You will need to specialize
665
- * `lz::custom_copier ` for your custom container if all of the following are true:
668
+ * `lz::custom_copier_for ` for your custom container if all of the following are true:
666
669
* - Your custom container does not have a `push_back` method
667
670
* - Your custom container does not have an `insert` method
668
671
* - Your custom container does not have an `insert_after` method (implicitly also requires `before_begin`)
@@ -682,9 +685,9 @@ LZ_NODISCARD constexpr Container to(Iterable&& iterable, Args&&... args) {
682
685
* }
683
686
* };
684
687
*
685
- * // Specialize `lz::custom_copier ` for your custom container
688
+ * // Specialize `lz::custom_copier_for ` for your custom container
686
689
* template<class T>
687
- * struct lz::custom_copier <custom_container<T>> {
690
+ * struct lz::custom_copier_for <custom_container<T>> {
688
691
* template<class Iterable>
689
692
* void copy(Iterable&& iterable, custom_container<T>& container) const {
690
693
* // Copy the contents of the iterable to the container. Container is already reserved
@@ -711,30 +714,30 @@ LZ_NODISCARD constexpr Cont to(Iterable&& iterable, Args&&... args) {
711
714
* Example:
712
715
* ```cpp
713
716
* template<class T>
714
- * class MyContainer {
717
+ * class my_container {
715
718
* void my_inserter(T t) { ... }
716
719
* };
717
- *
720
+ *
718
721
* template<class T>
719
- * lz::custom_copier<MyContainer <T>> {
722
+ * lz::custom_copier_for<my_container <T>> {
720
723
* template<class Iterable>
721
- * void copy(Iterable&& iterable, MyContainer <T>& container) {
724
+ * void copy(Iterable&& iterable, my_container <T>& container) {
722
725
* // Copy the iterable to the container, for example:
723
- * // Container is already reserved if it contains a reserve member function
726
+ * // Container is already reserved if it contains a reserve member function and iterable is sized
724
727
* for (auto&& i : iterable) {
725
728
* container.my_inserter(i);
726
729
* }
727
730
* }
728
731
* };
729
- *
732
+ *
730
733
* // or you can use enable if
731
734
* template<class T>
732
- * lz::custom_copier<MyContainer <T>, std::enable_if_t<...>> {
735
+ * lz::custom_copier_for<my_container <T>, std::enable_if_t<...>> {
733
736
* // Same as above
734
737
* };
735
738
* ```
736
739
*/
737
- using detail::custom_copier ;
740
+ using detail::custom_copier_for ;
738
741
739
742
LZ_MODULE_EXPORT_SCOPE_END
740
743
0 commit comments