8#include <initializer_list>
22template<
typename ITER,
typename VAL>
23[[nodiscard]]
constexpr bool contains(ITER first, ITER last,
const VAL& val)
26 while (first != last) {
27 if (*first == val)
return true;
32template<
typename RANGE,
typename VAL>
33[[nodiscard]]
constexpr bool contains(
const RANGE& range,
const VAL& val)
38template<
typename ITER,
typename VAL,
typename Proj>
39[[nodiscard]]
bool contains(ITER first, ITER last,
const VAL& val, Proj proj)
42 while (first != last) {
43 if (std::invoke(proj, *first) == val)
return true;
48template<
typename RANGE,
typename VAL,
typename Proj>
49[[nodiscard]]
bool contains(
const RANGE& range,
const VAL& val, Proj proj)
62template<
typename ITER,
typename VAL,
typename Proj = std::
identity>
63[[nodiscard]] ITER
find_unguarded(ITER first, ITER last,
const VAL& val, Proj proj = {})
66 [&](
const auto&
e) {
return std::invoke(proj,
e) == val; });
68template<
typename RANGE,
typename VAL,
typename Proj = std::
identity>
69[[nodiscard]]
auto find_unguarded(RANGE& range,
const VAL& val, Proj proj = {})
78template<
typename ITER,
typename PRED>
83 assert(first != last);
84 if (pred(*first))
return first;
88template<
typename RANGE,
typename PRED>
99template<
typename RANGE,
typename VAL,
typename Proj = std::
identity>
102 auto it =
find_unguarded(std::rbegin(range), std::rend(range), val, proj);
107template<
typename RANGE,
typename PRED>
124template<
typename VECTOR>
137 if (&*it != &v.back()) {
138 *it = std::move(v.back());
159template<
typename ForwardIt,
typename OutputIt,
typename UnaryPredicate>
161 ForwardIt first, ForwardIt last, OutputIt out_true, UnaryPredicate p)
164 auto out_false = first;
167 while (first != last) {
169l_true: *out_true++ = std::move(*first++);
171 *out_false++ = std::move(*first++);
175 return std::pair(out_true, out_false);
178template<
typename ForwardRange,
typename OutputIt,
typename UnaryPredicate>
186template<
typename ForwardRange,
typename UnaryOperation>
195template<
typename InputIterator,
typename Proj = std::
identity>
196[[nodiscard]]
auto min_value(InputIterator first, InputIterator last, Proj proj = {})
198 assert(first != last);
199 auto result = std::invoke(proj, *first++);
200 while (first != last) {
201 result =
std::min(result, std::invoke(proj, *first++));
206template<
typename InputRange,
typename Proj = std::
identity>
207[[nodiscard]]
auto min_value(InputRange&& range, Proj proj = {})
214template<
typename InputIterator,
typename Proj = std::
identity>
215[[nodiscard]]
auto max_value(InputIterator first, InputIterator last, Proj proj = {})
217 assert(first != last);
218 auto result = std::invoke(proj, *first++);
219 while (first != last) {
220 result =
std::max(result, std::invoke(proj, *first++));
225template<
typename InputRange,
typename Proj = std::
identity>
226[[nodiscard]]
auto max_value(InputRange&& range, Proj proj = {})
235template<
typename InputRange,
typename Proj = std::
identity>
236[[nodiscard]]
auto sum(InputRange&& range, Proj proj = {})
239 using VT =
typename std::iterator_traits<Iter>::value_type;
240 using RT =
decltype(std::invoke(proj, std::declval<VT>()));
245 while (first != last) {
246 init = std::move(init) + std::invoke(proj, *first++);
253 template<
typename T,
typename Iterator>
255 std::is_same_v<T, void>,
256 typename std::iterator_traits<Iterator>::value_type,
265template<
typename T =
void,
typename Range>
283template<
typename... Ranges>
289template<
typename Result>
295template<
typename Result,
typename Range,
typename... Tail>
296void append(Result& x, Range&& y, Tail&&... tail)
305 x.emplace_back(std::forward<
decltype(
e)>(
e));
316template<
typename Result,
typename T2,
typename... Tail>
317void append(Result& x, std::vector<T2>&& y, Tail&&... tail)
328template<
typename T,
typename... Tail>
329void append(std::vector<T>& v, Tail&&... tail)
332 auto current = v.size();
333 auto required = current + extra;
334 if (v.capacity() < required) {
335 v.reserve(current +
std::max(current, extra));
344void append(std::vector<T>& v, std::vector<T>&& range)
347 v = std::move(range);
351 std::move_iterator(
std::end(range)));
356void append(std::vector<T>& x, std::initializer_list<T> list)
358 x.insert(x.end(), list);
362template<
typename T = void,
typename Range,
typename... Tail>
363[[nodiscard]]
auto concat(
const Range& range, Tail&&... tail)
366 std::vector<T2> result;
367 append(result, range, std::forward<Tail>(tail)...);
371template<
typename T,
typename... Tail>
372[[nodiscard]] std::vector<T>
concat(std::vector<T>&& v, Tail&&... tail)
374 append(v, std::forward<Tail>(tail)...);
380template<
typename T,
size_t X,
size_t Y>
381constexpr auto concatArray(
const std::array<T, X>& x,
const std::array<T, Y>& y)
383 std::array<T, X + Y> result = {};
386 for (
size_t i = 0; i < X; ++i) result[0 + i] = x[i];
387 for (
size_t i = 0; i < Y; ++i) result[X + i] = y[i];
391template<
typename T,
size_t X,
size_t Y,
size_t Z>
393 const std::array<T, Y>& y,
394 const std::array<T, Z>& z)
396 std::array<T, X + Y + Z> result = {};
397 for (
size_t i = 0; i < X; ++i) result[ i] = x[i];
398 for (
size_t i = 0; i < Y; ++i) result[X + i] = y[i];
399 for (
size_t i = 0; i < Z; ++i) result[X + Y + i] = z[i];
405template<
typename Key,
typename Value>
406[[nodiscard]]
const Value*
lookup(
const std::map<Key, Value>& m,
const Key& k)
409 return (it != m.end()) ? &it->second :
nullptr;
412template<
typename Key,
typename Value>
413[[nodiscard]] Value*
lookup(std::map<Key, Value>& m,
const Key& k)
416 return (it != m.end()) ? &it->second :
nullptr;
420template<
class... Ts>
struct overloaded : Ts... {
using Ts::operator()...; };
431template<
typename T,
typename... Ts>
433 : std::integral_constant<size_t, std::variant<get_index_tag<Ts>...>(get_index_tag<T>()).index()> {};
439template<
typename T,
typename F,
size_t... Is>
440[[nodiscard]]
static constexpr auto generate_array(
F f, std::index_sequence<Is...>)
441 -> std::array<T,
sizeof...(Is)>
446template<
size_t N,
typename F>
447[[nodiscard]]
static constexpr auto generate_array(
F f)
449 using T =
decltype(f(0));
450 return generate_array<T>(f, std::make_index_sequence<N>{});
std::conditional_t< std::is_same_v< T, void >, typename std::iterator_traits< Iterator >::value_type, T > ToVectorType
constexpr size_t sum_of_sizes(const Ranges &... ranges)
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
auto find_if(InputRange &&range, UnaryPredicate pred)
auto transform(InputRange &&range, OutputIter out, UnaryOperation op)
auto distance(octet_iterator first, octet_iterator last)
overloaded(Ts...) -> overloaded< Ts... >
ITER find_unguarded(ITER first, ITER last, const VAL &val, Proj proj={})
Faster alternative to 'find' when it's guaranteed that the value will be found (if not the behavior i...
const Value * lookup(const std::map< Key, Value > &m, const Key &k)
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))> >
std::pair< OutputIt, ForwardIt > partition_copy_remove(ForwardIt first, ForwardIt last, OutputIt out_true, UnaryPredicate p)
This is like a combination of partition_copy() and remove().
constexpr ITER find_if_unguarded(ITER first, ITER last, PRED pred)
Faster alternative to 'find_if' when it's guaranteed that the predicate will be true for at least one...
auto min_value(InputIterator first, InputIterator last, Proj proj={})
void append(std::vector< T > &v, Tail &&... tail)
auto max_value(InputIterator first, InputIterator last, Proj proj={})
constexpr auto concatArray(const std::array< T, X > &x, const std::array< T, Y > &y)
auto transform_in_place(ForwardRange &&range, UnaryOperation op)
auto sum(InputRange &&range, Proj proj={})
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
auto rfind_unguarded(RANGE &range, const VAL &val, Proj proj={})
Similar to the find(_if)_unguarded functions above, but searches from the back to front.
auto concat(const Range &range, Tail &&... tail)
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
constexpr auto rfind_if_unguarded(RANGE &range, PRED pred)
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)