50 template <
typename DownSignalPtr,
typename ...Inputs>
51 auto operator () (DownSignalPtr s, Inputs&& ...is) const
54 s->push_down(tuplify(std::forward<Inputs>(is)...));
58 template <
typename DownSignalPtr,
typename ...Inputs>
59 auto operator () (DownSignalPtr s)
const
67 template <
typename T,
typename Err>
68 auto default_construct_or_throw()
69 -> estd::enable_if_t<std::is_default_constructible<T>::value, T>
74 template <
typename T,
typename Err>
75 auto default_construct_or_throw()
76 -> estd::enable_if_t<!std::is_default_constructible<T>::value, T>
84 template <
typename XForm = identity_t,
85 typename ParentsPack = meta::pack<>,
86 template<
class>
class Base = down_signal>
87 class xform_down_signal;
89 template <
typename XForm,
91 template<
class>
class Base>
92 class xform_down_signal<XForm, meta::pack<Parents...>, Base>
93 :
public Base<xform::result_of_t<XForm, meta::value_t<Parents>...> >
95 using base_t = Base<xform::result_of_t<XForm, meta::value_t<Parents>...> >;
96 using down_rf_t = decltype(std::declval<XForm>()(send_down_r));
98 std::tuple<std::shared_ptr<Parents>...> parents_;
101 using value_type =
typename base_t::value_type;
103 xform_down_signal(xform_down_signal&&) =
default;
104 xform_down_signal(
const xform_down_signal&) =
delete;
105 xform_down_signal& operator=(xform_down_signal&&) =
default;
106 xform_down_signal& operator=(
const xform_down_signal&) =
delete;
108 template <
typename XForm2>
109 xform_down_signal(XForm2&& xform, std::shared_ptr<Parents> ...parents)
110 : base_t([&]() -> value_type {
112 return xform(xform::last_rf)(detail::no_value{}, parents->current()...);
114 catch (
const no_value_error&) {
115 return default_construct_or_throw<value_type, no_value_error>();
118 , parents_(std::move(parents)...)
119 , down_step_(xform(send_down_r))
123 void recompute() final
124 { recompute(estd::make_index_sequence<
sizeof...(Parents)>{}); }
126 void recompute_deep() final
127 { recompute_deep(estd::make_index_sequence<
sizeof...(Parents)>{}); }
129 std::tuple<std::shared_ptr<Parents>...>& parents()
131 const std::tuple<std::shared_ptr<Parents>...>& parents()
const
135 template <std::size_t ...Indices>
136 void recompute(estd::index_sequence<Indices...>)
138 down_step_(
this, std::get<Indices>(parents_)->current()...);
141 template <std::size_t ...Indices>
142 void recompute_deep(estd::index_sequence<Indices...>)
145 (std::get<Indices>(parents_)->recompute_deep(),
150 down_rf_t down_step_;
160 template <
typename UpSignalPtr,
typename ...Inputs>
161 auto operator () (UpSignalPtr s, Inputs&& ...is) const
164 s->push_up(tuplify(std::forward<Inputs>(is)...));
174 template <
typename ReducingFnT,
typename UpdateT>
180 template <
typename XformUpSignalPtr,
typename ...Inputs>
181 auto operator () (XformUpSignalPtr s, Inputs&& ...is) const
184 auto indices = estd::make_index_sequence<
185 std::tuple_size<
estd::decay_t<decltype(s->parents())> >::value > {};
186 return step(s, updater(peek_parents(s, indices),
187 std::forward<Inputs>(is)...));
190 template <
typename XformUpSignalPtr, std::size_t ...Indices>
191 auto peek_parents(XformUpSignalPtr s, estd::index_sequence<Indices...>) const
194 tuplify(
std::get<Indices>(s->parents())->current()...)))
209 template <typename UpdateT>
210 auto update(UpdateT&& updater)
211 -> xform::transducer_impl<update_rf_gen, estd::
decay_t<UpdateT> >
213 return std::forward<UpdateT>(updater);
219 template <
typename XForm = identity_t,
220 typename SetXForm = identity_t,
221 typename ParentsPack = meta::pack<>,
222 template<
class>
class Base = up_down_signal>
223 class xform_up_down_signal;
225 template <
typename XForm,
228 template<
class>
class Base>
229 class xform_up_down_signal<XForm, SetXForm, meta::pack<Parents...>, Base>
230 :
public xform_down_signal<XForm, meta::pack<Parents...>, Base>
232 using base_t = xform_down_signal<XForm, meta::pack<Parents...>, Base>;
233 using up_rf_t = decltype(std::declval<SetXForm>()(send_up_rf));
236 using value_type =
typename base_t::value_type;
238 xform_up_down_signal(xform_up_down_signal&&) =
default;
239 xform_up_down_signal(
const xform_up_down_signal&) =
delete;
240 xform_up_down_signal& operator=(xform_up_down_signal&&) =
default;
241 xform_up_down_signal& operator=(
const xform_up_down_signal&) =
delete;
243 template <
typename XForm2,
typename SetXForm2>
244 xform_up_down_signal(XForm2&& xform,
245 SetXForm2&& set_xform,
246 std::shared_ptr<Parents> ...parents)
247 : base_t(
std::forward<XForm2>(xform),
std::move(parents)...)
248 , up_step_(set_xform(send_up_rf))
251 void send_up(
const value_type& value)
final
254 estd::make_index_sequence<
sizeof...(Parents)>{});
257 void send_up(value_type&& value) final
259 send_up(std::move(value),
260 estd::make_index_sequence<
sizeof...(Parents)>{});
263 template <
typename T>
264 void push_up(T&& value)
266 push_up(std::forward<T>(value),
267 estd::make_index_sequence<
sizeof...(Parents)>{});
271 template <
typename T, std::size_t... Indices>
272 void send_up(T&& x, estd::index_sequence<Indices...>)
274 up_step_(
this, std::forward<T>(x));
277 template <
typename T, std::size_t ...Indices>
278 void push_up(T&& value, estd::index_sequence<Indices...>)
280 auto& parents = this->parents();
282 (std::get<Indices>(parents)->send_up(
283 std::get<Indices>(std::forward<T>(value))),
287 template <
typename T>
288 void push_up(T&& value, estd::index_sequence<0>)
290 std::get<0>(this->parents())->send_up(std::forward<T>(value));
300 template <
typename SignalT>
301 auto link_to_parents(std::shared_ptr<SignalT> signal)
302 -> std::shared_ptr<SignalT>
304 return link_to_parents(
306 estd::make_index_sequence<std::tuple_size<
311 template <
typename SignalT, std::size_t ...Indices>
312 auto link_to_parents(std::shared_ptr<SignalT> signal,
313 estd::index_sequence<Indices...>)
314 -> std::shared_ptr<SignalT>
316 auto& parents = signal->parents();
318 (std::get<Indices>(parents)->link(signal),
327 template <
typename XForm,
typename ...Parents>
328 auto make_xform_down_signal(XForm&& xform,
329 std::shared_ptr<Parents> ...parents)
331 xform_down_signal<estd::decay_t<XForm>,
332 meta::pack<Parents...> >
335 using signal_t = xform_down_signal<estd::decay_t<XForm>,
336 meta::pack<Parents...> >;
337 return link_to_parents(
338 std::make_shared<signal_t>(std::forward<XForm>(xform),
339 std::move(parents)...));
345 template <
typename XForm,
348 auto make_xform_up_down_signal(XForm&& xform,
349 SetXForm&& set_xform,
350 std::shared_ptr<Parents> ...parents)
352 xform_up_down_signal<estd::decay_t<XForm>,
353 estd::decay_t<SetXForm>,
354 meta::pack<Parents...> >
357 using signal_t = xform_up_down_signal<estd::decay_t<XForm>,
358 estd::decay_t<SetXForm>,
359 meta::pack<Parents...> >;
360 return link_to_parents(
361 std::make_shared<signal_t>(std::forward<XForm>(xform),
362 std::forward<SetXForm>(set_xform),
363 std::move(parents)...));
#define ABL_DECLTYPE_RETURN(body_expr)
Utility for defining generic functions with a deduced return type, that are composed of a single expr...
typename std::decay< T >::type decay_t
Similar to C++14 std::decay_t.
This module implements the signal flow in funken.
C++ amazing templates and reusable implementations awesomeness.