@@ -46,9 +46,9 @@ class functional_vector
4646 : backing_vector_(vector)
4747 {
4848 }
49-
49+
5050 explicit functional_vector (std::vector<T>&& vector)
51- : backing_vector_(std::move(vector))
51+ : backing_vector_(std::move(vector))
5252 {
5353 }
5454 explicit functional_vector (std::initializer_list<T> list)
@@ -86,6 +86,72 @@ class functional_vector
8686 return functional_vector<U>(transformed_vector);
8787 }
8888
89+ // Returns true if all elements match the predicate (return true)
90+ //
91+ // example:
92+ // functional_vector<int> numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});
93+ //
94+ // // returns true
95+ // numbers.all_of([](const auto &number) {
96+ // return number < 10;
97+ // });
98+ //
99+ // // returns false
100+ // numbers.all_of([](const auto &number) {
101+ // return number > 2;
102+ // });
103+ template <typename Callable, typename = std::enable_if_t <std::is_invocable_r<bool , Callable, T>::value>>
104+ bool all_of (Callable && unary_predicate) const
105+ {
106+ return std::all_of (cbegin (),
107+ cend (),
108+ std::forward<Callable>(unary_predicate));
109+ }
110+
111+ // Returns true if at least one of the elements matches the predicate (returns true)
112+ //
113+ // example:
114+ // functional_vector<int> numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});
115+ //
116+ // // returns true
117+ // numbers.any_of([](const auto &number) {
118+ // return number < 5;
119+ // });
120+ //
121+ // // returns false
122+ // numbers.any_of([](const auto &number) {
123+ // return number > 9;
124+ // });
125+ template <typename Callable, typename = std::enable_if_t <std::is_invocable_r<bool , Callable, T>::value>>
126+ bool any_of (Callable && unary_predicate) const
127+ {
128+ return std::any_of (cbegin (),
129+ cend (),
130+ std::forward<Callable>(unary_predicate));
131+ }
132+
133+ // Returns true if no element matches the predicate (all return false)
134+ //
135+ // example:
136+ // functional_vector<int> numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});
137+ //
138+ // // returns true
139+ // numbers.none_of([](const auto &number) {
140+ // return number < -2;
141+ // });
142+ //
143+ // // returns false
144+ // numbers.none_of([](const auto &number) {
145+ // return number > 7;
146+ // });
147+ template <typename Callable, typename = std::enable_if_t <std::is_invocable_r<bool , Callable, T>::value>>
148+ bool none_of (Callable && unary_predicate) const
149+ {
150+ return std::none_of (cbegin (),
151+ cend (),
152+ std::forward<Callable>(unary_predicate));
153+ }
154+
89155 // Performs the functional `filter` algorithm, in which all elements of this instance
90156 // which match the given predicate are kept (mutating)
91157 //
@@ -194,7 +260,7 @@ class functional_vector
194260 struct is_valid_iterator {
195261 static bool const value = std::is_constructible_v<deref_type<Iterator>>;
196262 };
197-
263+
198264 // Performs the functional `zip` algorithm, in which every element of the resulting vector is a
199265 // tuple of this instance's element (first) and the second vector's element (second) at the same
200266 // index. The sizes of the two vectors must be equal.
@@ -427,8 +493,8 @@ class functional_vector
427493 [[nodiscard]] std::optional<size_t > find_first_index (const T& element) const
428494 {
429495 if (auto const it = std::find (backing_vector_.cbegin (),
430- backing_vector_.cend (),
431- element); it != backing_vector_.cend ())
496+ backing_vector_.cend (),
497+ element); it != backing_vector_.cend ())
432498 {
433499 return std::distance (backing_vector_.cbegin (), it);
434500 }
@@ -451,8 +517,8 @@ class functional_vector
451517 [[nodiscard]] std::optional<size_t > find_last_index (const T& element) const
452518 {
453519 if (auto const it = std::find (backing_vector_.crbegin (),
454- backing_vector_.crend (),
455- element); it != backing_vector_.crend ())
520+ backing_vector_.crend (),
521+ element); it != backing_vector_.crend ())
456522 {
457523 return std::distance (it, backing_vector_.crend ()) - 1 ;
458524 }
@@ -1056,18 +1122,73 @@ class functional_vector
10561122 return backing_vector_.size ();
10571123 }
10581124
1125+ // Clears the vector by removing all elements (mutating)
1126+ functional_vector& clear ()
1127+ {
1128+ backing_vector_.clear ();
1129+ return *this ;
1130+ }
1131+
1132+ // Returns true if the vector has no elements
1133+ bool is_empty () const
1134+ {
1135+ return size () == 0 ;
1136+ }
1137+
1138+ // Returns the underlying capacity of the vector, which can be larger from its size
1139+ size_t capacity () const
1140+ {
1141+ return backing_vector_.capacity ();
1142+ }
1143+
1144+ // Reserves the necessary memory for `count` elements, so that subsequent changes in the
1145+ // vector's size due to addition/removal of elements is more performant
1146+ functional_vector& reserve (size_t count)
1147+ {
1148+ backing_vector_.reserve (count);
1149+ return *this ;
1150+ }
1151+
1152+ // Resizes the vector to have given number of elements
1153+ // If `count` is larger than the current `size`, then `count-size` default elements are inserted at the back
1154+ // If `count` is smaller than the current `size`, then the last `size - count` elements are removed
1155+ //
1156+ // example:
1157+ // // numbers.capacity() = 9
1158+ // // numbers.size() = 9
1159+ // functional_vector<int> numbers({1, 4, 2, 5, 8, 3, 1, 7, 1});
1160+
1161+ // // numbers.capacity() = 9
1162+ // // numbers.size() = 5
1163+ // // numbers -> functional_vector<int>({1, 4, 2, 5, 8});
1164+ // numbers.resize(5);
1165+ //
1166+ // // empty_numbers.capacity() = 0
1167+ // // empty_numbers.size() = 0
1168+ // functional_vector<int> empty_numbers;
1169+ //
1170+ // // empty_numbers.capacity() = 5
1171+ // // empty_numbers.size() = 5
1172+ // // empty_numbers -> functional_vector<int>({0, 0, 0, 0, 0});
1173+ // empty_numbers.resize(5);
1174+ functional_vector& resize (size_t count)
1175+ {
1176+ backing_vector_.resize (count);
1177+ return *this ;
1178+ }
1179+
10591180 // Returns the begin iterator, useful for other standard library algorithms
10601181 [[nodiscard]] typename std::vector<T>::iterator begin ()
10611182 {
10621183 return backing_vector_.begin ();
10631184 }
1064-
1185+
10651186 // Returns the const begin iterator, useful for other standard library algorithms
10661187 [[nodiscard]] typename std::vector<T>::const_iterator cbegin () const
10671188 {
10681189 return backing_vector_.begin ();
10691190 }
1070-
1191+
10711192 // Returns the end iterator, useful for other standard library algorithms
10721193 [[nodiscard]] typename std::vector<T>::iterator end ()
10731194 {
@@ -1160,10 +1281,10 @@ class functional_vector
11601281
11611282 template <typename Iterator, typename = std::enable_if_t <is_valid_iterator<Iterator>::value>>
11621283 [[nodiscard]] auto zip_impl ( const Iterator& vec_begin, const Iterator & vec_end) const ->
1163- functional_vector<functional_pair<deref_type<Iterator>>>
1284+ functional_vector<functional_pair<deref_type<Iterator>>>
11641285 {
11651286 using U = deref_type<Iterator>;
1166-
1287+
11671288 const auto vec_size = std::distance (vec_begin, vec_end);
11681289 assert (backing_vector_.size () == vec_size);
11691290 std::vector<functional_pair<U>> combined_vector;
0 commit comments