Factories¶
array_ptr
¶
-
template<typename T>
class array_ptr : public inline_sequence_base<array_ptr<T>>¶ A type with “fat” pointer semantics, implemented as a
(pointer, length)
pair. It can be used across API boundaries as a “type erased” contiguous sequence. It is the Flux-native equivalent ofstd::span
.All
array_ptr
s are trivially movable. IfT
isconst
thenarray_ptr
is additionally trivially copyable, otherwise it is move-only.For the purposes of documentation below, the exposition-only concept
non_slicing_ptr_convertible
is defined as:template <typename From, typename To> concept non_slicing_ptr_convertible = std::convertible_to<From (*)[], To (*)[]>;
- Constructors:
-
template<contiguous_sequence Seq>
requires see_below
explicit array_ptr(Seq &seq);¶
-
template<typename U>
requires (!std::same_as<U, T> && non_slicing_ptr_convertible<U, T>)
array_ptr(array_ptr<U> const &other) noexcept;¶ Implicit conversion constructor from a compatible
array_ptr
.
- Friend functions:
-
friend auto operator==(array_ptr lhs, array_ptr rhs) -> bool;¶
Equivalent to:
lhs.data() == rhs.data() && lhs.size() == rhs.size()
but ensures that the pointer comparison is always well defined.
Note
array_ptr
has pointer semantics, and so equality comparison tests the addresses of the pointed-to objects.If you want to check whether the elements of two
array_ptr
s compare equal, you can useflux::equal()
.
empty
¶
from_istream
¶
-
template<std::default_initializable T, typename CharT, typename Traits>
auto from_istream(std::basic_istream<CharT, Traits> &is) -> sequence auto;¶ Returns a single-pass, read-only sequence which yields successive
T
s extracted fromis
using operator>>(). The element type of the returned sequence is T const&.
from_istreambuf
¶
-
template<typename CharT, typename Traits>
auto from_istreambuf(std::basic_streambuf<CharT, Traits> *buf) -> sequence auto;¶
-
template<typename CharT, typename Traits>
auto from_istreambuf(std::basic_istream<CharT, Traits> &is) -> sequence auto;¶ Returns a single-pass, read-only sequence which yields successive characters from the given streambuf using
std::basic_streambuf::sgetc()
. Iteration is complete when the streambuf reaches EOF.The second overload is equivalent to:
from_streambuf(is.rdbuf())
from_range
¶
generator
¶
-
template<typename ElemT>
class generator¶
getlines
¶
ints
¶
-
auto ints() -> random_access_sequence auto;¶
-
auto ints(distance_t from) -> random_access_sequence auto;¶
-
auto ints(distance_t from, distance_t to) -> random_access_sequence auto;¶
iota
¶
-
template<typename T>
requires see_below
auto iota(T from) -> multipass_sequence auto;¶
-
template<typename T>
requires see_below
auto iota(T from, T to) -> multipass_sequence auto;¶
repeat
¶
-
template<typename T>
requires std::movable<std::decay_t<T>>
auto repeat(T &&obj) -> infinite_sequence auto;¶
-
template<typename T>
requires std::movable<std::decay_t<T>>
auto repeat(T &&obj, std::integral auto count) -> random_access_sequence auto;¶ Returns a sequence which yields a const reference to
obj
endlessly (for the first overload) or exactlycount
times (for the second overload).For both overloads, the returned sequence is always a
random_access_sequence
. For the second overload it additionally modelssized_sequence
andbounded_sequence
.Caution
In order to provide random-access functionality, cursors for repeat sequences keep a
size_t
count of how many times they have been incremented. For very long-running programs using the infinite version ofrepeat()
it may be possible to overflow this counter. (Assuming 1000 iterations per second, this would take approximately 49 days on a machine with a 32-bitsize_t
, or around 500 million years on a 64-bit machine.)While this won’t cause undefined behaviour, calling
distance()
with cursors that have rolled over may give incorrect results, and may result in a runtime error in debug mode if the result cannot be represented as adistance_t
.- Parameters:
obj – A movable object which will be stored in the returned sequence object
count – If provided, a non-negative value to indicate the size of the returned sequence. If not provided, the returned sequence will be infinite.
- Returns:
A sequence which repeatedly yields a const reference to
obj
- Example:
// flux::repeat(val) is a random-access sequence which endlessly repeats // the given value auto seq = flux::repeat(3); auto cursor = flux::first(seq); assert(flux::read_at(seq, cursor) == 3); // fast-forward the cursor a lot... cursor = flux::next(seq, cursor, 1'000'000); assert(flux::read_at(seq, cursor) == 3); // still returning 3! // We could use the take adaptor to make a repeat sequence finite... auto taken = flux::take(seq, 5); assert(flux::equal(taken, std::array{3, 3, 3, 3, 3})); // ...but it's easier to use repeat(val, count) instead auto police = flux::repeat("hello"sv, 3); assert(flux::equal(police, std::array{"hello", "hello", "hello"}));
- See also:
single
¶
-
template<typename T>
requires std::move_constructible<T>
auto single(T &&obj) -> contiguous_sequence auto;¶
unfold
¶
-
template<typename Func, typename Seed>
requires see_below
auto unfold(Func func, Seed &&seed) -> infinite_sequence auto;¶ Generates an infinite single-pass sequence by repeatedly invoking the unary function
func
, starting with the givenseed
.Whereas
fold()
takes a sequence and a function and produces a single value,unfold()
does the opposite: it takes a function and a single value an produces a sequence.Let
R
be std::decay_t<std::invoke_result_t<Func&, Seed>>. The sequence object contains variable state of typeR
, which is initialised fromseed
. At every call toinc()
, the internal state is updated as if by:state = std::invoke(func, std::move(state));
A call to
read_at()
returns a read-only reference to the internal state, with type R const&.Note
As the provided function can potentially be called again and again “forever”, it’s important to make sure that this can’t cause undefined behaviour, for example by signed integer overflow – perhaps by using unsigned ints instead, or by ensuring that iteration is terminated before this occurs.
- Requires:
Let
R
be std::decay_t<std::invoke_result_t<Func&, Seed>>. Then the expression in therequires
clause is equivalent to:std::constructible_from<R, Seed> && std::invocable<Func&, R> && std::assignable_from<R&, std::invoke_result_t<Func&, R>>
- Parameters:
func – A unary callable with a signature compatible with
R(R)
seed – The initial seed value. Must be convertible to the result type of
func
.
- Returns:
An infinite single-pass sequence generated by repeated invocations of
func
, starting with theseed
value.- Example:
// We can use unfold() with the identity function to do the equivalent of // flux::repeat(): auto repeated = flux::unfold(std::identity{}, "hello"sv).take(3); assert(flux::equal(repeated, std::array{"hello"sv, "hello"sv, "hello"sv})); // We can combine unfold() with a mutable lambda to do more sophisticated // things, like generating the Fibonacci sequence: auto fibs = flux::unfold([next = 1u](unsigned cur) mutable { return std::exchange(next, cur + next); }, 0u); assert(flux::equal(std::move(fibs).take(10), std::array<unsigned, 10>{0, 1, 1, 2, 3, 5, 8, 13, 21, 34}));
- See also: