In the Design section we say how a transducer may extend the state from the reducing function. Not only does this allow it to include feedback in the process, but also to signal to process whether the computation has terminated.
This section describes the abstract interface that comunicates between the state and the reducing process, and also the concrete state wrapping utilities provided for transducer implementors.
state_traits_t = state_traits<std::decay_t<T>>decltype(auto) zug::state_complete(T && s)Convenience function for calling state_traits::complete
zug::state_is_reduced(T &&s)¶Convenience function for calling state_traits::is_reduced
decltype(auto) zug::state_data(T && s, D && d)Convenience function for calling state_traits::data
decltype(auto) zug::state_unwrap(T && s)Convenience function for calling state_traits::unwrap
decltype(auto) zug::state_unwrap_all(T && s)Convenience function for calling state_traits::unwrap_all
decltype(auto) zug::state_rewrap(T && s, U && x)Convenience function for calling state_traits::unwrap_all
zug::state_traits¶Interface for a type specializing the State concept.
A State is the first parameter of a reducing function, also known as the accumulator. Every type is a model of State, with the following default implementation. However, one might want to specialize the state it for a particular accumulator type, such that transducers can operate with it. A transducer should not make assumptions about the state it receives, instead, it can only wrap it using wrap_state to attach additional data.
For an example of a stateful reducing function, see take.
zug::wrap_state(StateT &&next, DataT &&data = DataT{})¶Given a tag TagT and a state next and associated data, returns a state_wrapper instance.
decltype(auto) zug::state_wrapper_unwrap(TagT, T && s)Utility function for easy overloading of state_traits::unwrap for state wrappers with a specific tag.
decltype(auto) zug::state_wrapper_complete(TagT, T && s)Utility function for easy overloading of state_traits::complete for state wrappers with a specific tag.
decltype(auto) zug::state_wrapper_unwrap_all(TagT, T && s)Utility function for easy overloading of state_traits::unwrap_all for state wrappers with a specific tag.
decltype(auto) zug::state_wrapper_rewrap(TagT, T && s, U && x)Utility function for easy overloading of state_traits::rewrap for state wrappers with a specific tag.
decltype(auto) zug::state_wrapper_data(TagT tag, T && s, D &&)Utility function for easy overloading of state_traits::data for state wrappers with a specific tag.
decltype(auto) zug::state_wrapper_data(T && s)decltype(auto) zug::state_wrapper_data(TagT, T && s)zug::state_wrapper_data_is_reduced(TagT, DataT&&)¶Utility function that returns whether the DataT associated with a state wrapper with tag TagT is reduced i.e. idempotent. Can be overloaded custom tags.
zug::state_wrapper_is_reduced(TagT tag, T &&s)¶Utility function for easy overloading of state_traits::is_reduced for state wrappers with a specific tag. Most of the time you may want to overload state_wrapper_is_reduced instead.
zug::no_tag¶Default tag for state_wrapper.
zug::state_wrapper¶A decorator for the accumulator of a reduction.
A transducer must not make any assumptions about the accumulator of the process it is helping to reduce. However, a stateful transducer may use a state_wrapper to attach extra data to the accumulator such that the reducing function object itself can be state-less.
A state wrapper has the following template arguments:
For an example of a stateful reducing function, see take.
TagT: is as tag type used to identify the transducer that is attaching the state. This can useful to specialize the state_traits for a concrete state wrapper.StateT: is the accumulator that is to be wrapped and of which we shall make no assumptions.DataT: is the additional data that the transducer wants to attach to represent its own state.zug::is_state_wrapper¶Metafunction returning whether StateT is a, or reference to, a state_wrapper instantiation.
zug::is_state_wrapper<_, state_wrapper<T, S, D>>¶zug::state_traits<state_wrapper<TagT, StateT, DataT>>¶State traits specialization for state_wrapper. Just forwards to the state_wrapper_* methods, that are easier to specialize for a given tag.
zug::with_state(StateT &&st, UnwrappedFn &&fn, WrappedFn &&fn)¶Given a value st that represents the state of a reduction, this function generically dispatches to the right function UnwrappedFn or WrappedFn, depending of whether the value is already wrapped or not. This is, during the first iteration of the reduction, UnwrappedFn will be called, from then on, WrappedFnT will be called.
The signatures should be of the form:
UnwrappedFn : A -> BWrappedFn : B -> BThis function can dispatch both statically and dynamically in a transparent way. It is thus very useful for writing stateful transducers that can be type erased in a transducer<> object.
maybe_reduced = state_wrapper<maybe_reduced_tag, T, bool>State wrapper for transducers that may want to signal that the reduction is finished.
zug::state_wrapper_data_is_reduced(maybe_reduced_tag, bool is_reduced)¶zug::reduced_if(T &&x, bool is_reduced)¶Wraps x in a maybe_reduced, where is_reduced contains whether the reduction should actually finish.
decltype(auto) zug::reduced(T && x)Wraps x such that the reduction should finish.
decltype(auto) zug::not_reduced(T && x)Wraps x such that the reduction should continue.
zug::maybe_reduced_tag¶Tag for maybe_reduced state wrapper.
skip_result_t = typename skip_result<ReducingFnT, StateT, InputTs...>::typezug::skip(ReducingFnT&&, StateT &&state, InputTs&&...)¶Skip calling the next reducing function in a transducer. Returns the state parameter, potentially wrapped in a value convertible to/from whatever call would return for similar parameters.
A transducer might or might not call the next reducing function in the chain. One good example is filter, where if the predicate passes, it calls the next reducing function, otherwise it just returns the current state of the reduction. However, this poses the question: what should be the return type of such a transducer? The next reducing function might wrap the state in a state_wrapper to attach its own state to it. However, we don’t know at this point what how to create such a wrapped value. This method, and call, take care of wrapping the state in a type that can hold values of both the current state, and the state that would be returned by the next reducing function. The metafunction skip_result defines such a type.
zug::skip(StateT &&state)¶zug::call(ReducingFnT &&step, StateT &&state, InputTs&&... ins)¶Call the next reducing function in a transducer that could otherwise skip calling the next reducing function. Returns the result of calling step(state, ins...) wrapped in a type that can also hold plain state values. If state is wrapped in such a type, it unwraps it before passing it.
zug::skip_state¶Type-safe union type that can hold values of both SkippedT and CalledT types.
zug::is_skip_state¶zug::is_skip_state<skip_state<SkippedT, CalledT>>¶zug::skip_result¶Metafunction that returns a type that can hold both values of type skipped_t = StateT and wrapped_t = declval<ReducingFnT>(declval<StateT>(), declval<InputTs>()...)
The result is:
std::common_type<skipped_t, wrapped_t> exists between the two types, it returns this type. For example, if one of these is a any_state because is used in a type erased transducer, any_state will be the result.skip_state<skipped_t, wrapped_t>, which is essentially a type-safe union of these two types. zug::any_state¶Polymorphically holds any value implementing the state_traits. This type is used for the implementation of transducer.