xformed.hpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2014, 2015 Ableton AG, Berlin. All rights reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21 //
22 
23 // Copyright: 2014, 2015, Ableton AG, Berlin. All rights reserved.
28 #pragma once
29 
30 #include <atria/funken/in.hpp>
31 #include <atria/funken/inout.hpp>
34 
35 namespace atria {
36 namespace funken {
37 
38 namespace detail {
39 
40 template <typename SignalT>
41 struct xformed_input : private input_impl<SignalT>
42 {
43  friend class access;
44  using impl_t = input_impl<SignalT>;
45  using typename impl_t::value_type;
46  using impl_t::impl_t;
47  using impl_t::get;
48 };
49 
50 template <typename SignalT>
51 struct xformed_inoutput : private inoutput_impl<SignalT>
52 {
53  friend class access;
54  using impl_t = inoutput_impl<SignalT>;
55  using typename impl_t::value_type;
56  using impl_t::impl_t;
57  using impl_t::get;
58  using impl_t::set;
59 };
60 
61 } // namespace detail
62 
69 template <typename Xform, typename ...InTs>
70 auto xformed(Xform&& xform, InTs&& ...ins)
72  meta::all(In_value<InTs>()...),
73  detail::xformed_input<
74  typename decltype(
75  detail::make_xform_down_signal(
76  xform, detail::access::signal(ins)...)
77  )::element_type
78  >
79  >
80 {
81  return detail::make_xform_down_signal(
82  std::forward<Xform>(xform),
83  detail::access::signal(std::forward<InTs>(ins))...);
84 }
85 
86 template <typename Xform, typename Xform2, typename ...InoutTs>
87 auto xformed(Xform&& xform, Xform2&& xform2, InoutTs&& ...ins)
89  (!In_value<Xform2>() && meta::all(Inout_value<InoutTs>()...)),
90  detail::xformed_inoutput<
91  typename decltype(
92  detail::make_xform_up_down_signal(
93  xform, xform2, detail::access::signal(ins)...)
94  )::element_type
95  >
96  >
97 {
98  return detail::make_xform_up_down_signal(
99  std::forward<Xform>(xform),
100  std::forward<Xform2>(xform2),
101  detail::access::signal(std::forward<InoutTs>(ins))...);
102 }
103 
108 using detail::update;
109 
110 namespace detail {
111 
112 struct at_rf_gen
113 {
114  template <typename ReducingFnT, typename KeyT>
115  struct apply
116  {
117  ReducingFnT step;
118  KeyT key;
119 
121  template <typename StateT, typename InT>
122  auto operator()(StateT&& s, InT&& i)
123  -> decltype(true
124  ? step(std::forward<StateT>(s), i.at(key))
125  : std::forward<StateT>(s))
126  {
127  try
128  {
129  return step(std::forward<StateT>(s), i.at(key));
130  }
131  catch (const std::out_of_range&)
132  {
133  return s;
134  }
135  }
136  };
137 };
138 
139 template <typename KeyT>
140 struct at_updater
141 {
142  KeyT key;
143 
144  template <typename CollectionT, typename ValueT>
145  CollectionT operator() (CollectionT col, ValueT&& v) const
146  {
147  try
148  {
149  col.at(key) = std::forward<ValueT>(v);
150  }
151  catch (const std::out_of_range&) {}
152  return col;
153  }
154 };
155 
156 } // namespace detail
157 
163 template <typename KeyT>
164 auto xat(KeyT&& key)
166 {
167  return std::forward<KeyT>(key);
168 }
169 
176 template <typename KeyT>
177 auto uat(KeyT&& key)
178  -> detail::at_updater<estd::decay_t<KeyT> >
179 {
180  return { std::forward<KeyT>(key) };
181 }
182 
189 template <typename KeyT, typename ...Ins>
190 auto atted(KeyT&& k, Ins&& ...ins)
192  meta::all(In_value<Ins>() && !Out_value<Ins>()...),
193  decltype(xformed(xat(k), ins...))
194  >
195 {
196  return xformed(xat(std::forward<KeyT>(k)),
197  std::forward<Ins>(ins)...);
198 }
199 
200 template <typename KeyT, typename ...Ins>
201 auto atted(KeyT&& k, Ins&& ...ins)
203  meta::all(Inout_value<Ins>()...),
204  decltype(xformed(xat(k), update(uat(k)), ins...))
205  >
206 {
207  return xformed(xat(k),
208  update(uat(k)),
209  std::forward<Ins>(ins)...);
210 }
211 
212 namespace detail {
213 
214 template <typename AttrPtr>
215 struct get_attr_fn
216 {
217  AttrPtr attr;
218 
220  template <typename T>
221  auto operator()(T&& x) const
222  -> ABL_DECLTYPE_RETURN(x.*attr)
223 };
224 
225 template <typename AttrPtr>
226 struct set_attr_fn
227 {
228  AttrPtr attr;
229  template <typename T, typename U>
230  auto operator()(T x, U&& v) const -> T
231  {
232  x.*attr = std::forward<U>(v);
233  modified(x);
234  return x;
235  }
236 };
237 
238 } // namespace detail
239 
244 template <typename AttrPtrT>
245 auto get_attr(AttrPtrT p) -> detail::get_attr_fn<AttrPtrT> { return { p }; }
246 
251 template <typename AttrPtrT>
252 auto set_attr(AttrPtrT p) -> detail::set_attr_fn<AttrPtrT>{ return { p }; }
253 
259 template <typename AttrPtrT, typename ...Ins>
260 auto attred(AttrPtrT attr, Ins&& ...ins)
262  meta::all(In_value<Ins>() && !Out_value<Ins>()...),
263  decltype(xformed(xform::map(get_attr(attr)), ins...))
264  >
265 {
266  return xformed(xform::map(get_attr(attr)),
267  std::forward<Ins>(ins)...);
268 }
269 
270 template <typename AttrPtrT, typename ...Ins>
271 auto attred(AttrPtrT attr, Ins&& ...ins)
273  meta::all(Inout_value<Ins>()...),
274  decltype(xformed(xform::map(get_attr(attr)),
275  update(set_attr(attr)), ins...))
276  >
277 {
278  return xformed(xform::map(get_attr(attr)),
279  update(set_attr(attr)),
280  std::forward<Ins>(ins)...);
281 }
282 
283 } // namespace funken
284 } // namespace atria
#define ABL_DECLTYPE_RETURN(body_expr)
Utility for defining generic functions with a deduced return type, that are composed of a single expr...
Definition: utils.hpp:109
typename std::enable_if< X, T >::type enable_if_t
Similar to C++14 std::enable_if_t.
Definition: type_traits.hpp:84
auto set_attr(AttrPtrT p) -> detail::set_attr_fn< AttrPtrT >
Returns a update function that uses the given pointer to member.
Definition: xformed.hpp:252
constexpr bool all()
Returns true if all the passed in values are true.
Definition: concept.hpp:70
auto attred(AttrPtrT attr, Ins &&...ins) -> estd::enable_if_t< meta::all(In_value< Ins >()&&!Out_value< Ins >()...), decltype(xformed(xform::map(get_attr(attr)), ins...)) >
Given a pointer to member, returns a xformed version of the ins accessed through the member...
Definition: xformed.hpp:260
Utility to write simple transducers easily.
auto modified(T &) -> estd::enable_if_t<!std::is_convertible< T &, structure< T > & >::value >
Call this on an structure value to indicate that is has indeed changed, invalidating its cached value...
Definition: structure.hpp:160
auto get_attr(AttrPtrT p) -> detail::get_attr_fn< AttrPtrT >
Returns a unary function that dereferences the given pointer to member to the applied objects...
Definition: xformed.hpp:245
auto atted(KeyT &&k, Ins &&...ins) -> estd::enable_if_t< meta::all(In_value< Ins >()&&!Out_value< Ins >()...), decltype(xformed(xat(k), ins...)) >
Returns xformed version of the ins using xat.
Definition: xformed.hpp:190
C++ amazing templates and reusable implementations awesomeness.
Definition: _doc.hpp:35
auto xformed(Xform &&xform, InTs &&...ins) -> estd::enable_if_t< meta::all(In_value< InTs >()...), detail::xformed_input< typename decltype( detail::make_xform_down_signal( xform, detail::access::signal(ins)...) )::element_type > >
Returns a new in formed by applying a transducer xform on the successive values of the in...
Definition: xformed.hpp:70
auto map(MappingT &&mapping) -> map_t< estd::decay_t< MappingT > >
Similar to clojure.core/map$1.
Definition: map.hpp:79
auto xat(KeyT &&key) -> xform::transducer_impl< detail::at_rf_gen, estd::decay_t< KeyT > >
Transducer that projects the key key from containers with a standard-style at() method.
Definition: xformed.hpp:164
auto uat(KeyT &&key) -> detail::at_updater< estd::decay_t< KeyT > >
Update function that updates the key in a container with a standard-style at() method.
Definition: xformed.hpp:177
Fork me on GitHub