unzip.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 
27 #pragma once
28 
32 
33 namespace atria {
34 namespace xform {
35 
36 namespace detail {
37 
38 using std::get;
39 
40 template <typename ResultT, typename ...Ts>
41 struct unzip_types_aux;
42 
43 template <typename ResultT>
44 struct unzip_types_aux<ResultT>
45 {
46  using type = ResultT;
47 };
48 
49 template <typename... ResultTs, typename T, typename... Ts>
50 struct unzip_types_aux<meta::pack<ResultTs...>, T, Ts...>
51  : unzip_types_aux<meta::pack<ResultTs...>,
52  meta::pack<T, meta::get_index_sequence<T> >,
53  Ts...>
54 {};
55 
56 template <typename... ResultTs,
57  typename T, std::size_t... Indexes,
58  typename... Ts>
59 struct unzip_types_aux<meta::pack<ResultTs...>,
60  meta::pack<T, estd::index_sequence<Indexes...> >,
61  Ts...>
62  : unzip_types_aux<meta::pack<ResultTs...,
63  decltype(get<Indexes>(std::declval<T>()))...>,
64  Ts...>
65 {};
66 
67 template <typename... ResultTs, typename T, typename... Ts>
68 struct unzip_types_aux<meta::pack<ResultTs...>,
69  meta::pack<T, meta::could_not_get_index_sequence>,
70  Ts...>
71  : unzip_types_aux<meta::pack<ResultTs..., T>, Ts...>
72 {};
73 
85 template <typename... Ts>
86 struct unzip_types : unzip_types_aux<meta::pack<>, Ts...> {};
87 
88 template <typename... Ts>
89 using unzip_types_t = typename unzip_types<estd::decay_t<Ts>... >::type;
90 
95 template <typename ReducingFnT, typename StateT, typename... InputTs>
96 struct unzip_result
97 {
98  template <typename... Ts>
99  struct apply : std::result_of<ReducingFnT(StateT, Ts...)> {};
100 
101  using type = meta::unpack_t<apply, unzip_types_t<InputTs...> >;
102 };
103 
104 template <typename ReducingFnT, typename StateT, typename... InputTs>
105 using unzip_result_t =
106  typename unzip_result<ReducingFnT, StateT, InputTs...>::type;
107 
108 struct unzip_rf_gen
109 {
110  template <typename ReducingFnT>
111  struct apply
112  {
113  ReducingFnT step;
114 
115  struct last_input_tag {};
116 
117  template <typename ResultT, std::size_t... Indexes,
118  typename StateT, typename InputT, typename... InputTs>
119  auto impl_apply(meta::pack<ResultT> r, estd::index_sequence<Indexes...>,
120  StateT&& s, InputT&& i, InputTs&& ...is)
121  -> ResultT
122  {
123  return impl(r,
124  std::forward<StateT>(s),
125  std::forward<InputTs>(is)...,
126  std::get<Indexes>(std::forward<InputT>(i))...);
127  }
128 
129  template <typename ResultT,
130  typename StateT, typename InputT, typename... InputTs>
131  auto impl_apply(meta::pack<ResultT> r, meta::could_not_get_index_sequence,
132  StateT&& s, InputT&& i, InputTs&& ...is)
133  -> ResultT
134  {
135  return impl(r,
136  std::forward<StateT>(s),
137  std::forward<InputTs>(is)...,
138  std::forward<InputT>(i));
139  }
140 
141  template <typename ResultT, typename StateT, typename InputT, typename... InputTs>
142  auto impl(meta::pack<ResultT>, StateT&& s, InputT&&, InputTs&& ...is)
144  std::is_same<estd::decay_t<InputT>, last_input_tag>{},
145  ResultT>
146  {
147  return step(std::forward<StateT>(s),
148  std::forward<InputTs>(is)...);
149  }
150 
151  template <typename ResultT, typename StateT, typename InputT, typename... InputTs>
152  auto impl(meta::pack<ResultT> r, StateT&& s, InputT&& i, InputTs&& ...is)
154  !std::is_same<estd::decay_t<InputT>, last_input_tag>{},
155  ResultT>
156  {
157  return impl_apply(
158  r,
159  meta::get_index_sequence<InputT>{},
160  std::forward<StateT>(s),
161  std::forward<InputT>(i),
162  std::forward<InputTs>(is)...);
163  }
164 
165  template <typename StateT, typename... InputTs>
166  auto operator() (StateT&& s, InputTs&& ...is)
167  -> unzip_result_t<ReducingFnT, StateT, InputTs...>
168  {
169  return impl(
170  meta::pack<unzip_result_t<ReducingFnT, StateT, InputTs...> >{},
171  std::forward<StateT>(s),
172  std::forward<InputTs>(is)...,
173  last_input_tag{});
174  }
175  };
176 };
177 
178 } // namespace detail
179 
180 
181 using unzip_t = transducer_impl<detail::unzip_rf_gen>;
182 
187 constexpr auto unzip = unzip_t {};
188 
189 } // namespace xform
190 } // namespace atria
typename std::enable_if< X, T >::type enable_if_t
Similar to C++14 std::enable_if_t.
Definition: type_traits.hpp:84
constexpr auto unzip
Transducer that expands all tuples in the inputs in the argument list of the next transducer...
Definition: unzip.hpp:187
Utility to write simple transducers easily.
C++ amazing templates and reusable implementations awesomeness.
Definition: _doc.hpp:35
Fork me on GitHub