The following templates implement a “derived value”. A derived value is a reference-counted subclass of a very important object that sets is value based on a varying list of other values. A set of functors define how a varying list of values derives some value, of the same or a different type.
#include <x/derivedvalue.H> typedef x::derivedvalue<int, std::string> derived_t; derived_t derived=x::derivedvalues<int>::create( [] { return (int)0; }, [] (int &sum, const int &v) { sum += v; }, [] (const int &sum) { std::ostringstream o; o << sum*2; return o.str(); });
This example creates a
x::w::derivedvalue
that's a std::string
which is derived from a list
of int
s.
x::derivedvalues<int>::create
()
creates this reference-counted object.
Its template parameter specifies the type of values the derived object
gets derived from. Three lambdas, given as arguments to
create
() calculate the derived value.
The “begin calculation” lambda's return value returns the initial value for the calculation.
The “calculation” lambda gets invoked for each value that the derived value is currently based on. It is not specified in which order each value is passed to the calculation lambda. The lambda's first parameter is a mutable reference to the current calculation value, and the second parameter is the next value that the final derived value gets derived from.
The “final value” lambda gets invoked after the last value, that the derived value is currently based on, gets passed to the calculation value, and it returns. If the list of values is empty, the begin calculation lambda gets called, and then the final value lambda gets called immediately afterwards.
The type that the final value returns sets the type of the
very important derived value. The above example creates a
std::string
from a list of
int
s by adding them together, multiplying the
sum by two, and converting it to a std::string
.
The calculated derived value gets compared to the current derived value
using the ==
operator. Only if the newly
calculated derived value does not compare as equal, does this
this still result in an update to
the derived value, and invocation of all the registered lambda callbacks.
x::derivedvaluelist<int>::base::current_value_t v=derived->create(1);
This create
() method adds a new value to the
list of values that the derived value gets calculated from.
current_value_t
is also a reference to a
reference-counted object. The initial value, of the added value, gets
passed to create
()'s constructor.
There's also an emplace
() method that
constructs a new value.
v=derived->create(1);
The derived value gets automatically recalculated whenever:
A new value gets create
()d.
The last reference to an existing
current_value_t
object goes out of scope,
and it gets destroyed.
An existing
current_value_t
's
update
() method gets invoked, which specifies
a new replacement for the referenced.
Any of these events result in invoking the three lambdas to calculate a new derived value based on the updated list of values that the derived value is based on.
typedef derived_value_t::base::vipobj_t vipobj_t; vipobj_t::handlerlock lock(*derived); std::string current_value=*vipobj_t::readlock(*derived); auto mcguffin=lock->install_back([] (const std::string &value) { }, current_value);
x::derivedvalue<
gives the type of the
value_type
, derived_value_type
>::base::vipobj_tx::vipobj
that the derived value is based on.
Use a handler lock to register callback lambdas to obtain the value of
the derived value.
The derived value object takes complete responsibility for using the underlying update lock and write lock, to set the new calculated value. These locks should not be used explicitly.
Each current_value_t
holds a reference to its
derivedvalue
, and it's not specified
in which order each value gets passed to the calculation lmabda,
during the calculation.