Algorithms¶
all
¶
-
template<sequence Seq, predicate_for<Seq> Pred>
auto all(Seq &&seq, Pred pred) -> bool;¶ Takes a
sequence
and a predicate and returns true if every element of the sequence satisfies the predicate. This algorithm is short-circuiting: it will stop iterating (returning false) as soon as it finds an element which does not satisfy the predicate.Returns true for an empty sequence.
Equivalent to is_last(seq, find_if_not(seq, pred)).
- Parameters:
seq – A sequence
pred – A callable which accepts a single argument of
seq
’s element type and returns bool
- Returns:
- Example:
auto is_small = [](int i) { return i < 10; }; std::vector<int> vec{1, 2, 3, 4, 5}; // Check whether every element is small bool all_small = flux::all(vec, is_small); assert(all_small);
any
¶
-
template<sequence Seq, predicate_for<Seq> Pred>
auto any(Seq &&seq, Pred pred) -> bool;¶ Takes a
sequence
and a predicate and returns true if any element in the sequence satisfies the predicate. This algorithm is short-circuiting: it will stop iterating (returning true) as soon as it has found a satisfactory element.Returns false for an empty sequence.
Equivalent to !is_last(seq, find_if(seq, pred)).
- Parameters:
seq – A sequence.
pred – A callable which accepts a single argument of
seq
’s element type and returns bool
- Returns:
- Example:
1auto is_even = [](int i) { return i % 2 == 0; }; 2 3std::vector<int> vec{1, 3, 4, 5, 7, 9}; 4 5bool b = flux::any(vec, is_even); 6assert(b == true); // There is an even element
compare
¶
-
template<sequence Seq1, sequence Seq2, typename Cmp = std::compare_three_way>
requires see_below
auto compare(Seq1 &&seq1, Seq2 &&seq2, Cmp cmp = {});¶ Performs a lexicographical three-way comparison between the elements of
seq1
andseq2
.This function iterates over both sequences in lock-step, and compares each respective pair of elements using
cmp
. If the elements are not equivalent, then the result of the comparison is returned. Otherwise, the next pair of elements is compared, and so on.Note
If you just want to know whether the two sequences contain the same elements, you should prefer
equal()
.If the end of one of the sequences is reached, then:
less is returned if the first sequence had fewer elements (was “less than”) the second
greater is returned if the second sequence had fewer elements (so the first sequence was “greater”)
Otherwise, all elements of both sequences were equivalent and so equivalent is returned
- Requires:
The comparator
cmp
must return a value of one of the standard comparison categories, that isstd::strong_ordering, or
std::weak_ordering, or
std::partial_ordering
- Parameters:
- Returns:
A value of the same comparison category as returned by
cmp
, indicating whether the first sequence is lexicographically less than, greater than or equivalent to the first, or if they are unordered.- Example:
1std::vector<int> v1{1, 2, 3, 4, 5}; 2 3std::vector<int> v2{1, 4, 9, 16, 25}; 4 5// Result is std::strong_ordering because ints have a total order, 6// and less because 2 < 4 7assert(flux::compare(v1, v2) == std::strong_ordering::less); 8 9// v1 compares equal to v1 10assert(std::is_eq(flux::compare(v1, v1))); 11 12std::vector<int> v3{1, 2, 3, 4, 5}; 13std::vector<int> v4{1, 2, 3}; 14 15// All elements compare equal, but v3 has more elements and so 16// is greater than v4 17assert(flux::compare(v3, v4) == std::strong_ordering::greater); 18 19// Note that sequences containing NaNs are unordered with the default comparator 20std::vector<double> v5{1.0, 2.0, 3.0, 4.0, 5.0}; 21std::vector<double> v6{1.0, 2.0, NAN, 4.0, 5.0}; 22assert(flux::compare(v5, v6) == std::partial_ordering::unordered); 23 24// On most systems we can use std::strong_order as a custom comparator 25// to get a total order for IEEE floats 26if constexpr (std::numeric_limits<double>::is_iec559) { 27 assert(flux::compare(v5, v6, std::strong_order) == 28 std::strong_ordering::less); 29}
contains
¶
-
template<sequence Seq, typename Value>
requires std::equality_comparable_with<element_t<Seq>, Value const&>
auto contains(Seq &&seq, Value const &value) -> bool;¶ Returns true if any element in
seq
compares equal tovalue
. This algorithm is short-circuiting: it will stop iterating as soon as it has found an equal element.Equivalent to !is_last(seq, find(seq, value))
- Parameters:
seq – A sequence
value – A value to search for
- Returns:
- Example:
1std::vector<std::string> const simpsons{ 2 "Homer", "Marge", "Bart", "Lisa", "Maggie" 3}; 4 5// Bart is a Simpson 6assert(flux::contains(simpsons, "Bart")); 7 8// Mr Burns is not a Simpson 9assert(not flux::contains(simpsons, "Mr Burns"));
- See also:
count
¶
-
auto count(sequence auto &&seq) -> distance_t;¶
Returns the number of elements in the sequence.
If
seq
is asized_sequence
then this is equivalent toflux::size()
. Otherwise,count()
will iterate over the sequence, “using up” single-pass sequences.Equivalent to:
if constexpr (sized_sequence<decltype(seq)>) { return size(seq); } else { return count_if(seq, pred::true_); }
- Parameters:
seq – A sequence
- Returns:
The number of elements in
seq
- Example:
1std::vector<int> vec{1, 2, 3}; 2 3// std::vector is a sized_sequence, so this call is 4// equivalent to `flux::size(vec)` (and so constant time) 5assert(flux::count(vec) == 3); 6 7// A filtered sequence is never sized, so this call will 8// iterate over each element 9auto filtered = flux::filter(std::move(vec), flux::pred::odd); 10assert(flux::count(filtered) == 2); 11 12// An istream sequence is single-pass and not sized, so counting 13// the elements will "use up" the sequence 14std::istringstream iss("1 2 3"); 15auto seq = flux::from_istream<int>(iss); 16assert(flux::count(seq) == 3); 17assert(flux::is_last(seq, flux::first(seq))); // No more elements!
count_eq
¶
-
template<sequence Seq, typename Value>
requires std::equality_comparable_with<element_t<Seq>, Value const&>
auto count_eq(Seq &&seq, Value const &value) -> distance_t;¶ Iterates over
seq
and returns the number of elements which compare equal tovalue
.Equivalent to count_if(seq, pred::eq(value)), but does not take a copy of
value
.
count_if
¶
-
template<typename Seq, typename Pred>
requires std::predicate<Pred&, element_t<Seq>>
auto count_if(Seq &&seq, Pred pred) -> distance_t;¶ Returns the number of elements in the sequence for which the predicate returned true.
Equivalent to:
fold(seq, [&pred](distance_t count, auto&& elem) { if (std::invoke(pred, std::forward(elem))) { ++count; } return count; }, distance_t{0})
ends_with
¶
-
template<sequence Seq1, sequence Seq2, typename Cmp = std::ranges::equal_to>
requires see_below
auto ends_with(Seq1 &&seq1, Seq2 &&seq2, Cmp cmp = {}) -> bool;¶ Returns true if
seq2
is a suffix ofseq1
according to the comparatorcmp
.If
Seq1
andSeq2
both satisfysized_sequence
andseq1
has fewer elements thanseq2
,starts_with()
immediately returns false and no comparisons are performed.- Requires:
Both
Seq1
andSeq2
must model eithermultipass_sequence
orsized_sequence
. Additionally, std::predicate<Cmp&, element_t<Seq1>, element_t<Seq2>> must be modelled.- Parameters:
seq1 – The “haystack” sequence
seq2 – The “needle” sequence
cmp – Predicate used to compare sequence elements, defaulting to
std::ranges::equal_to
.
- Returns:
- Example:
1std::string_view greeting = "Hello world"; 2 3// greeting has "world" as a suffix 4assert(flux::ends_with(greeting, "world"sv)); 5 6std::vector numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 7 8// numbers ends with [8, 9, 10] 9assert(flux::ends_with(numbers, std::array{8, 9, 10}));
- See also:
equal
¶
-
template<sequence Seq1, sequence Seq2, typename Cmp = std::equal_to<>>
requires std::predicate<Cmp&, element_t<Seq1>, element_t<Seq2>>
auto equal(Seq1 &&seq1, Seq2 &&seq2, Cmp cmp = {}) -> bool;¶ Returns true if
seq1
andseq2
have the same number of elements and each corresponding pair of elements compares equal according tocmp
.If
seq1
andseq2
both satisfysized_sequence
and their sizes differ,equal()
immediately returns false and no comparisons are performed.When using the default comparators, equal(seq1, seq2) returns the same answer as std::is_eq(compare(seq1, seq2)) but may be more efficient.
fill
¶
find
¶
find_if
¶
find_if_not
¶
find_max
¶
-
template<multipass_sequence Seq, weak_ordering_for<Seq> Cmp = std::compare_three_way>
auto find_max(Seq &&seq, Cmp cmp = {}) -> cursor_t<Seq>;¶ Returns a cursor to the maximum element of
seq
, compared usingcmp
.If several elements are equally maximal,
find_max()
returns a cursor to the last such element.Note
This behaviour differs from
std::max_element()
, which returns an iterator to the first maximal element.- Parameters:
seq – A multipass sequence
cmp – A comparator to use to find the maximum element, defaulting to
std::compare_three_way
- Returns:
A cursor pointing to the maximum element of
seq
.- Example:
1struct Person { 2 std::string name; 3 int age; 4}; 5 6std::vector<Person> people{ 7 {"Alice", 44}, 8 {"Bob", 63}, 9 {"Chris", 29}, 10 {"Dani", 29}, 11 {"Eddy", 63} 12}; 13 14// Get a cursor to the maximum of the people vector, according to age 15auto max_cur = flux::find_max(people, flux::proj(flux::cmp::compare, &Person::age)); 16 17// The oldest person is 63 18assert(flux::read_at(people, max_cur).age == 63); 19 20// Note that (unlike std::max_element) find_max() return a cursor to the 21// *last* of several equally-maximum elements 22assert(flux::read_at(people, max_cur).name == "Eddy");
find_min
¶
-
template<multipass_sequence Seq, weak_ordering_for<Seq> Cmp = std::compare_three_way>
auto find_min(Seq &&seq, Cmp cmp = {}) -> cursor_t<Seq>;¶ Returns a cursor to the minimum element of
seq
, compared usingcmp
.If several elements are equally minimal,
find_min()
returns a cursor to the first such element.- Parameters:
seq – A multipass sequence
cmp – A comparator to use to find the minimum element, defaulting to
std::compare_three_way
- Returns:
A cursor pointing to the minimum element of
seq
.- Example:
1struct Person { 2 std::string name; 3 int age; 4}; 5 6std::vector<Person> people{ 7 {"Alice", 44}, 8 {"Bob", 63}, 9 {"Chris", 29}, 10 {"Dani", 29}, 11 {"Eddy", 63} 12}; 13 14// Get a cursor to the maximum of the people vector, according to age 15auto min_cur = flux::find_min(people, flux::proj(flux::cmp::compare, &Person::age)); 16 17// The youngest person is 29 18assert(flux::read_at(people, min_cur).age == 29); 19 20// Note that find_min() return a cursor to the first of several 21// equally-minimum elements 22assert(flux::read_at(people, min_cur).name == "Chris");
find_minmax
¶
-
template<multipass_sequence Seq, weak_ordering_for<Seq> Cmp = std::compare_three_way>
auto find_minmax(Seq &&seq, Cmp cmp = {}) -> minmax_result<cursor_t<Seq>>;¶ Returns a pair of cursors to the minimum and maximum elements of
seq
, compared usingcmp
.If several elements are equally minimal,
find_minmax()
returns a cursor to the first. If several elements are equally maximal,find_minmax()
returns a cursor to the last.Equivalent to:
minmax_element<cursor_t<Seq>>{.min = find_min(seq, cmp), .max = find_max(seq, cmp)};
but only does a single pass over
seq
.- Parameters:
seq – A multipass sequence
cmp – A comparator to use to find the maximum element, defaulting to
std::compare_three_way
- Returns:
A cursor pointing to the maximum element of
seq
.- Example:
1struct Person { 2 std::string name; 3 int age; 4}; 5 6std::vector<Person> people{ 7 {"Alice", 44}, 8 {"Bob", 63}, 9 {"Chris", 29}, 10 {"Dani", 29}, 11 {"Eddy", 63} 12}; 13 14// find_minmax() returns a pair of cursors which we can destructure 15// Here we'll get the min and max of the people vector, according to age 16auto [min, max] = flux::find_minmax(people, flux::proj(flux::cmp::compare, &Person::age)); 17 18// The "minimum" is Chris. Dani is the same age, but Chris appears earlier 19// in the sequence 20assert(flux::read_at(people, min).name == "Chris"); 21 22// The "maximum" is Eddy. Bob is the same age, but Eddy appears later in the 23// sequence 24assert(flux::read_at(people, max).name == "Eddy");
- See also:
fold
¶
fold_first
¶
for_each
¶
for_each_while
¶
inplace_reverse
¶
-
template<bidirectional_sequence Seq>
requires bounded_sequence<Seq> && element_swappable_with<Seq, Seq>
auto inplace_reverse(Seq &&seq) -> void;¶
max
¶
min
¶
minmax
¶
-
template<typename T>
struct minmax_result;¶
none
¶
output_to
¶
product
¶
search
¶
sort
¶
-
template<random_access_sequence Seq, typename Cmp = std::compare_three_way>
requires see_below
auto sort(Seq &&seq, Cmp cmp = {}) -> void;¶
starts_with
¶
-
template<sequence Seq1, sequence Seq2, typename Cmp = std::ranges::equal_to>
requires std::predicate<Cmp&, element_t<Seq1>, element_t<Seq2>>
auto starts_with(Seq1 &&seq1, Seq2 &&seq2, Cmp cmp = {}) -> bool;¶ Returns true if
seq2
is a prefix ofseq1
according to the comparatorcmp
.If
Seq1
andSeq2
both satisfysized_sequence
andseq1
has fewer elements thanseq2
,starts_with()
immediately returns false and no comparisons are performed.- Parameters:
seq1 – The “haystack” sequence
seq2 – The “needle” sequence
cmp – Predicate used to compare sequence elements, defaulting to
std::ranges::equal_to
.
- Returns:
- Example:
1std::string_view greeting = "Hello world"; 2 3// greeting has "Hello" as a prefix 4assert(flux::starts_with(greeting, "Hello"sv)); 5 6std::vector numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 7 8// numbers begins with [1, 2, 3] 9assert(flux::starts_with(numbers, std::array{1, 2, 3}));
- See also:
sum
¶
swap_elements
¶
to
¶
-
template<typename Container>
requires see_below
auto to(sequence auto &&seq, auto&&... args) -> Container;¶
-
template<template<typename...> typename Container>
requires see_below
auto to(sequence auto &&seq, auto&&... args);¶ Converts a Flux sequence to a container, for example a std::vector.
The first overload takes a “complete” container type name as its template argument, for example std::vector<int> or std::list<std::string>. The second overload takes a template name as its template argument, for example just std::vector or std::map, and will then use CTAD to deduce the appropriate template arguments.
The optional extra arguments provided to
flux::to()
, denoted args... above, will be forwarded to the selected container constructor as detailed below. The intention is to allow using (for example) custom allocator arguments.Let C be the target container type (either explicitly specified for the first overload, or deduced via CTAD). If the sequence’s element type is convertible to C::value_type, then
flux::to()
will try to construct a C using the following methods, in order of priority:Direct sequence construction using C(std::forward(seq), std::forward(args)...)
Note
If C is the same type as seq, this allows it to be copy- or move-constructed
Tagged sequence construction using C(flux::from_sequence, std::forward(seq), std::forward(args)...)
(In C++23) Tagged range construction as if by:
auto sub = std::ranges::subrange(begin(seq), end(seq)); return C(std::from_range, sub, std::forward(args)...);
C++17 iterator pair construction, as if by:
auto view = std::ranges::subrange(begin(seq), end(seq)) | std::views::common; return C(view.begin(), view.end(), std::forward(args)...);
Inserting elements as if by:
auto container = C(std::forward(args)...); output_to(std::forward(seq), range_inserter); return container;
where range_inserter is std::back_inserter(container) if the container has a compatible push_back() member function, or std::inserter(container, container.end()) otherwise. Will also attempt to call container.reserve() if possible to avoid reallocations during construction.
If the sequence’s element type is convertible to the container’s value type but none of the above methods work, compilation will fail.
If the sequence’s element type itself satisfies
sequence
, but is not convertible to the container value type, then flux::to<C>(seq, args...) is equivalent to:flux::to<C>(flux::map(std::forward(seq), [](auto&& elem) { flux::to<typename C::value_type>(std::forward(elem)); }), std::forward(args)...);
That is,
to()
will attempt to first convert each inner sequence to the container value type before proceeding as above.- Template Parameters:
Container – A type name (for the first overload) or a template name (for the second overload) which names a compatible container type
- Parameters:
seq – A sequence to be converted to a container
args – Optional extra arguments to be forwarded to the container constructor
- Example:
- See also: