pack.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 
29 #include <ableton/build_system/Warnings.hpp>
30 ABL_DISABLE_WARNINGS
31 #include <boost/mpl/sequence_tag.hpp>
32 #include <boost/mpl/pop_front_fwd.hpp>
33 #include <boost/mpl/push_front_fwd.hpp>
34 #include <boost/mpl/push_back_fwd.hpp>
35 #include <boost/mpl/front_fwd.hpp>
36 #include <boost/mpl/empty_fwd.hpp>
37 #include <boost/mpl/size_fwd.hpp>
38 #include <boost/mpl/at_fwd.hpp>
39 #include <boost/mpl/back_fwd.hpp>
40 #include <boost/mpl/clear_fwd.hpp>
41 #include <boost/mpl/pop_back_fwd.hpp>
42 #include <boost/mpl/iterator_tags.hpp>
43 #include <boost/mpl/next_prior.hpp>
44 #include <boost/mpl/deref.hpp>
45 #include <boost/mpl/begin_end_fwd.hpp>
46 ABL_RESTORE_WARNINGS
47 #include <type_traits>
48 
49 namespace atria {
50 namespace meta {
51 
56 template <typename ...Ts>
57 struct pack
58 {
59 };
60 
64 template <typename... Ts1, typename... Ts2>
65 constexpr bool operator== (const pack<Ts1...>&, const pack<Ts2...>&)
66 {
67  return std::is_same<pack<Ts1...>, pack<Ts2...> >{};
68 }
69 
73 template <typename... Ts1, typename... Ts2>
74 constexpr bool operator!= (const pack<Ts1...>&, const pack<Ts2...>&)
75 {
76  return !std::is_same<pack<Ts1...>, pack<Ts2...> >{};
77 }
78 
79 namespace detail {
80 
81 template <template<typename...> class MF, typename ArgT>
82 struct unpack
83 {
84  using type = MF<ArgT>;
85 };
86 
87 template <template<typename...> class MF, typename... ArgTs>
88 struct unpack<MF, meta::pack<ArgTs...> >
89 {
90  using type = MF<ArgTs...>;
91 };
92 
93 } // namespace detail
94 
100 template <template<typename...> class MF, typename T>
101 using unpack = typename detail::unpack<MF, T>::type;
102 
103 template <template<typename...> class MF, typename T>
104 using unpack_t = typename unpack<MF, T>::type;
105 
106 struct pack_tag;
107 
108 template <class ... Args>
110 
111 template <class ... Args>
112 struct pack_iterator<atria::meta::pack<Args...>>
113 {
114  typedef atria::meta::pack_tag tag;
115  typedef boost::mpl::forward_iterator_tag category;
116 };
117 
118 } // namespace meta
119 } // namespace atria
120 
121 namespace boost {
122 namespace mpl {
123 
124 template <class ... Args>
125 struct sequence_tag<atria::meta::pack<Args...>>
126 {
127  typedef atria::meta::pack_tag type;
128 };
129 
130 template <>
131 struct front_impl<atria::meta::pack_tag>
132 {
133  template <typename PackT> struct apply;
134  template <typename T, typename ...Ts>
135  struct apply<atria::meta::pack<T, Ts...>>
136  {
137  using type = T;
138  };
139 };
140 
141 template <>
142 struct empty_impl<atria::meta::pack_tag>
143 {
144  template <typename PackT> struct apply;
145  template <typename ...Ts>
146  struct apply<atria::meta::pack<Ts...>>
147  : std::integral_constant<bool, sizeof...(Ts) == 0>
148  {};
149 };
150 
151 template <>
152 struct pop_front_impl<atria::meta::pack_tag>
153 {
154  template <typename PackT> struct apply;
155  template <class First, class ...Types>
156  struct apply<atria::meta::pack<First, Types...>>
157  {
158  typedef atria::meta::pack<Types...> type;
159  };
160 };
161 
162 template <>
163 struct push_front_impl<atria::meta::pack_tag>
164 {
165  template <typename PackT, typename T> struct apply;
166  template <typename T, typename ... Args>
167  struct apply<atria::meta::pack<Args...>, T>
168  {
169  typedef atria::meta::pack<T, Args...> type;
170  };
171 };
172 
173 template <>
174 struct push_back_impl<atria::meta::pack_tag>
175 {
176  template <typename PackT, typename T> struct apply;
177  template <typename T, typename ... Args >
178  struct apply<atria::meta::pack<Args...>, T>
179  {
180  typedef atria::meta::pack<Args..., T> type;
181  };
182 };
183 
184 template <>
185 struct size_impl<atria::meta::pack_tag>
186 {
187  template <typename PackT> struct apply;
188  template <typename ...Ts>
189  struct apply<atria::meta::pack<Ts...>>
190  : std::integral_constant<std::size_t, sizeof...(Ts)>
191  {};
192 };
193 
194 template <>
195 struct at_impl<atria::meta::pack_tag>
196 {
197  template <typename T>
198  struct apply
199  {
200  static_assert(std::is_same<T, T>::value, "not implemented");
201  };
202 };
203 
204 template <>
205 struct back_impl<atria::meta::pack_tag>
206 {
207  template <typename T>
208  struct apply
209  {
210  static_assert(std::is_same<T, T>::value, "not implemented");
211  };
212 };
213 
214 template <>
215 struct clear_impl<atria::meta::pack_tag>
216 {
217  template <typename PackT>
218  struct apply
219  {
220  typedef atria::meta::pack<> type;
221  };
222 };
223 
224 template <>
225 struct pop_back_impl<atria::meta::pack_tag>
226 {
227  template <typename T>
228  struct apply
229  {
230  static_assert(std::is_same<T, T>::value, "not implemented");
231  };
232 };
233 
234 template <>
235 struct begin_impl<atria::meta::pack_tag>
236 {
237  template <class PackT> struct apply
238  {
240  };
241 };
242 
243 template <>
244 struct end_impl<atria::meta::pack_tag>
245 {
246  template <typename> struct apply
247  {
250  };
251 };
252 
253 template <typename First, class ... Args>
254 struct deref<atria::meta::pack_iterator<
255  atria::meta::pack<First, Args...>>>
256 {
257  typedef First type;
258 };
259 
260 template <typename First, class ... Args>
261 struct next<atria::meta::pack_iterator<
262  atria::meta::pack<First, Args...>>>
263 {
265  atria::meta::pack<Args...>> type;
266 };
267 
268 } // namespace mpl
269 } // namespace boost
constexpr bool operator!=(const pack< Ts1... > &, const pack< Ts2... > &)
Two packs are different if they are of different types.
Definition: pack.hpp:74
Definition: pack.hpp:121
constexpr bool operator==(const pack< Ts1... > &, const pack< Ts2... > &)
Two packs are equal if they are of the same type.
Definition: pack.hpp:65
MPL-compatible sequence that just holds a vector of types as a paremeter pack.
Definition: pack.hpp:57
typename detail::unpack< MF, T >::type unpack
Metafunction that given a variadic template MF and a type ArgT, returns MF, or if ArgT is of th...
Definition: pack.hpp:101
C++ amazing templates and reusable implementations awesomeness.
Definition: _doc.hpp:35
Fork me on GitHub