Go to the documentation of this file.
9 #ifndef EAGINE_VALUE_WITH_HISTORY_HPP
10 #define EAGINE_VALUE_WITH_HISTORY_HPP
21 value_with_history_changed(
const T& a,
const T& b) noexcept ->
bool {
22 return !are_equal(a, b);
27 value_with_history_delta(
const T& new_value,
const T& old_value) noexcept {
28 return new_value - old_value;
32 value_with_history_delta(
bool new_value,
bool old_value) noexcept ->
int {
33 return int(new_value) - int(old_value);
38 value_with_history_distance(
const T& new_value,
const T& old_value) noexcept {
40 return abs(value_with_history_delta(new_value, old_value));
50 template <
typename T, std::
size_t N>
57 template <
typename... I,
typename = std::enable_if_t<
sizeof...(I) == N>>
59 : _values{T(initial)...} {}
63 for(std::size_t i = 0; i < N; ++i) {
69 constexpr
auto get(std::size_t i)
const noexcept ->
const T& {
75 void set(std::size_t i,
const T& value) noexcept {
83 for(std::size_t i = 1; i < N; ++i) {
84 _values[N - i] = _values[N - i - 1];
91 for(std::size_t i = 1; i < N; ++i) {
92 _values[i] = _values[0];
100 template <
typename Transform,
typename... T, std::size_t N>
101 static inline auto transform_stored_values(
102 Transform transform_op,
103 const value_with_history_storage<T, N>&... v) {
104 value_with_history_storage<
105 decltype(std::declval<Transform>()(std::declval<T>()...)),
109 for(std::size_t i = 0; i < N; ++i) {
110 result.set(i, transform_op(v.get(i)...));
115 template <
typename Delta,
typename T, std::
size_t N>
116 static inline auto differentiate_stored_values(
118 const value_with_history_storage<T, N>& v) {
119 value_with_history_storage<
120 decltype(std::declval<Delta>()(std::declval<T>(), std::declval<T>())),
124 for(std::size_t i = 1; i < N; ++i) {
125 result.set(i - 1, delta_op(v.get(i - 1), v.get(i)));
130 template <
typename U,
typename T, std::
size_t N>
132 convert_stored_values(
const value_with_history_storage<T, N>& storage) {
133 return transform_stored_values([](
const T& v) {
return U(v); }, storage);
140 template <
typename T, std::
size_t N>
144 : _values{storage} {}
147 template <
typename... I>
149 : _values{std::forward<I>(initial)...} {}
158 auto get() const noexcept {
179 auto value(
bool old)
const noexcept {
185 operator T() const noexcept {
189 template <
typename U,
typename... P>
190 operator valid_if<U, P...>()
const noexcept {
202 differentiate_stored_values(
203 [](
const T& n,
const T& o) {
204 return value_with_history_delta(n, o);
220 template <
typename U>
236 auto _update_value(
const T& new_value) noexcept ->
bool {
238 if(value_with_history_changed(
values().
get(0), new_value)) {
240 values().set(0, new_value);
246 auto _advance_value(
const T& delta_value) noexcept ->
bool {
252 value_with_history() =
default;
254 explicit value_with_history(
const T& initial) noexcept
255 : _values(initial) {}
258 static_assert(N >= 2,
"at least two values are required");
259 value_with_history_storage<T, N> _values;
262 template <
typename Transform,
typename... T, std::size_t N>
264 transform(Transform transform_op,
const value_with_history<T, N>&... v) {
265 return value_with_history<
266 decltype(std::declval<Transform>()(std::declval<T>()...)),
267 N>(transform_stored_values(transform_op, v.values()...));
270 template <
typename T1,
typename T2, std::
size_t N>
271 static inline auto operator*(
272 const value_with_history<T1, N>& v1,
273 const value_with_history<T2, N>& v2) noexcept {
275 [](
const T1& t1,
const T2& t2) {
return t1 * t2; }, v1, v2);
278 template <
typename T1,
typename T2, std::
size_t N>
279 static inline auto operator/(
280 const value_with_history<T1, N>& v1,
281 const value_with_history<T2, N>& v2) noexcept {
283 [](
const T1& t1,
const T2& t2) {
return t1 / t2; }, v1, v2);
290 template <
typename T, std::
size_t N>
301 auto assign(
const T& new_value) ->
bool {
302 return this->_update_value(new_value);
307 return this->_advance_value(delta_value);
311 template <
typename T,
typename... P, std::size_t N>
312 class variable_with_history<valid_if<T, P...>, N>
313 :
public value_with_history<T, N> {
316 : value_with_history<T, N>(initial.value()) {}
318 auto assign(
const valid_if<T, P...>& new_value) ->
bool {
319 return this->_update_value(new_value.value());
322 auto advance(
const valid_if<T, P...>& delta_value) ->
bool {
323 return this->_advance_value(delta_value.value());
329 #endif // EAGINE_VALUE_WITH_HISTORY_HPP
auto values() const noexcept -> const value_with_history_storage< T, N > &
Returns a reference to the value storage.
Definition: value_with_history.hpp:152
void set(std::size_t i, const T &value) noexcept
Sets the i-th revision of the stored value (0 = current value).
Definition: value_with_history.hpp:75
auto distance() const noexcept
Returns the distance between the current and the previous revisions.
Definition: value_with_history.hpp:210
Base storage class for values and variables with history.
Definition: value_with_history.hpp:51
constexpr value_with_history_storage(I &&... initial)
Initializes the individual revisions of the value.
Definition: value_with_history.hpp:58
Common code is placed in this namespace.
Definition: eagine.hpp:21
auto value() const noexcept
Returns the current revision of the value.
Definition: value_with_history.hpp:165
auto changed() const noexcept -> bool
Indicates if the current and previous revisions differ.
Definition: value_with_history.hpp:215
void sync() noexcept
Synchronize the historic revisions to the current value.
Definition: value_with_history.hpp:90
Primary template for conditionally valid values.
Definition: decl.hpp:49
constexpr value_with_history(I &&... initial)
Initialized the individual revisions of this value.
Definition: value_with_history.hpp:148
void sync()
Synchronize the historic revisions to the current value.
Definition: value_with_history.hpp:227
constexpr auto get(std::size_t i) const noexcept -> const T &
Returns the i-th revision of the stored value (0 = current value).
Definition: value_with_history.hpp:69
auto delta() const noexcept
Returns the difference between the current and the previous revision.
Definition: value_with_history.hpp:195
auto as() const
Returns this with the values cast to new type U.
Definition: value_with_history.hpp:221
Class for read-only values with history.
Definition: value_with_history.hpp:141
void make_history() noexcept
Move the stored revisions by one, to make place for new value.
Definition: value_with_history.hpp:82
auto value(bool old) const noexcept
Returns the current or previous revision of the value.
Definition: value_with_history.hpp:179
constexpr value_with_history_storage(const T &initial) noexcept
Initializes all revisions with the same initial value.
Definition: value_with_history.hpp:62
auto old_value() const noexcept
Returns the previous revision of the value.
Definition: value_with_history.hpp:172
auto deltas() const noexcept
Returns the differences between the adjacent revisions.
Definition: value_with_history.hpp:200
auto advance(const T &delta_value) -> bool
Shifts the revisions and advanced the current value by given delta.
Definition: value_with_history.hpp:306
constexpr value_with_history_storage()=default
Default constructor.
constexpr variable_with_history() noexcept=default
Default constructor.
auto get() const noexcept
Returns the current revision of the value.
Definition: value_with_history.hpp:158
constexpr variable_with_history(const T &initial) noexcept
Initialize the all revisions to the initial value.
Definition: value_with_history.hpp:297
auto assign(const T &new_value) -> bool
Shifts the revisions and assigns a new value.
Definition: value_with_history.hpp:301
Class for mutable variables with history.
Definition: value_with_history.hpp:291