Tomographer  v3.0
Tomographer C++ Framework Documentation
needownoperatornew.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef TOMOGRAPHER_TOOLS_NEEDOWNOPERATORNEW_H
29 #define TOMOGRAPHER_TOOLS_NEEDOWNOPERATORNEW_H
30 
39 #include <type_traits>
40 
41 #include <Eigen/Eigen> // EIGEN_MAKE_ALIGNED_OPERATOR_NEW
42 
43 #include <tomographer/tools/cxxutil.h> // tomo_internal::sfinae_yes, tomo_internal::sfinae_no
44 
45 
46 namespace Tomographer {
47 namespace Tools {
48 
49 
54  template<typename T>
56 };
57 
58 
59 namespace tomo_internal {
60 
61 // see http://stackoverflow.com/a/9154394/1694896
62 template<typename T> static auto test_has_ownopnewprovidertype_member(int)
63  -> typename sfinae_yes<typename T::OperatorNewProviderType>::yes&;
64 template<typename T> static auto test_has_ownopnewprovidertype_member(long)
65  -> typename sfinae_no<>::no&;
66 template<typename T>
67 struct has_ownopnewprovidertype_member {
68  static constexpr bool value = (sizeof(tomo_internal::test_has_ownopnewprovidertype_member<T>(0))
69  == sizeof(typename tomo_internal::sfinae_yes<>::yes));
70 };
71 template<bool has_own_provider, typename T>
72 struct need_own_op_new_prov_helper {
73  typedef NoSpecialOperatorNewProvider ProviderType;
74 };
75 template<typename T>
76 struct need_own_op_new_prov_helper<true, T> {
77  typedef typename T::OperatorNewProviderType ProviderType;
78 };
79 } // namespace tomo_internal
80 
81 
135 template<typename... Types>
137  // will be specialized appropriately.
138 };
139 
140 
144 template<typename T>
146  typedef typename tomo_internal::need_own_op_new_prov_helper<
148  T
150  ProviderType;
151 
152  typedef typename ProviderType::template OperatorNewAllocatorType<T>::Type AllocatorType;
153 };
154 
155 
156 //
157 // Dark magic for allowing a struct to have several members of possibly different struct
158 // types (such as a ValueCalculator and a HistogramTypes), each of which might possibly
159 // require their own operator-new-providers; those super-structures should inherit from
160 // NeedOwnOperatorNew<Type1,Type2,Type3,...>::ProviderType , which resolves to the
161 // provider-type of all these types if they are the same (or if they don't require a
162 // provider-type).
163 //
164 
165 template<typename Type1, typename Type2, typename... OtherTypes>
166 struct NeedOwnOperatorNew<Type1, Type2, OtherTypes...>;
167 
168 
169 namespace tomo_internal {
170 
171 template<bool same_provider_type, bool t1_trivial_provider, bool t2_trivial_provider,
172  typename Type1, typename Type2, typename... OtherTypes>
173 struct need_own_operator_new_combination_helper {
174  // missing ProviderType member, will generate runtime error.
175  static_assert(!same_provider_type && !t1_trivial_provider && !t2_trivial_provider,
176  "ERROR: you have a type which requested a NeedOwnOperatorNew<T1,T2> "
177  "with incompatible needs.") ;
178 };
179 // case same_provider_type == true
180 template<bool t1_trivial_provider, bool t2_trivial_provider,
181  typename Type1, typename Type2, typename... OtherTypes>
182 struct need_own_operator_new_combination_helper<true, t1_trivial_provider, t2_trivial_provider,
183  Type1, Type2, OtherTypes...> {
184  // Type1 and Type2 have same provider, all ok, so continue and recurse on the other types:
185  typedef typename NeedOwnOperatorNew<Type1, OtherTypes...>::ProviderType ProviderType;
186 };
187 // case t1_trivial_provider == true
188 template<bool t2_trivial_provider,
189  typename Type1, typename Type2, typename... OtherTypes>
190 struct need_own_operator_new_combination_helper<false, true, t2_trivial_provider,
191  Type1, Type2, OtherTypes...> {
192  // all ok, use Type2's provider, and recurse on the other types
193  typedef typename NeedOwnOperatorNew<Type2, OtherTypes...>::ProviderType ProviderType;
194 };
195 // case t2_trivial_provider == true (and t1_trivial_provider == false, otherwise see case above)
196 template<typename Type1, typename Type2, typename... OtherTypes>
197 struct need_own_operator_new_combination_helper<false, false, true,
198  Type1, Type2, OtherTypes...> {
199  // all ok, use Type2's provider, and recurse on the other types
200  typedef typename NeedOwnOperatorNew<Type1, OtherTypes...>::ProviderType ProviderType;
201 };
202 
203 
204 } // namespace tomo_internal
205 
206 
207 template<typename Type1, typename Type2, typename... OtherTypes>
208 struct NeedOwnOperatorNew<Type1, Type2, OtherTypes...>
209 {
210  typedef tomo_internal::need_own_operator_new_combination_helper<
213  std::is_same<typename NeedOwnOperatorNew<Type1>::ProviderType,
217  Type1, Type2, OtherTypes...
218  > ProviderType;
219 };
220 
221 
222 
223 
224 
225 
226 
227 
228 //
229 // for Eigen types
230 //
231 
232 
233 
238 public:
239  EIGEN_MAKE_ALIGNED_OPERATOR_NEW ;
241 
242  template<typename T> struct OperatorNewAllocatorType {
244  };
245 
246 #ifdef TOMOGRAPHER_TEST_TOOLS_NEEDOWNOPERATORNEW_DEBUG_MEMBERS
247  // DEBUG: provide something we can test that it is indeed eigen-aligned
249  : EigenAlignedOperatorNewIsActive(true)
250  {
251  }
252  const bool EigenAlignedOperatorNewIsActive;
253 #endif
254 };
255 
256 
260 
261  // prevent inadvertently inheriting this class instead of
262  // EigenAlignedOperatorNewProvider:
263  NeedEigenAlignedOperatorNew() = delete;
264 };
265 
266 
271 template<typename Scalar, int FixedRows, int FixedCols, int Options, int MaxRows, int MaxCols>
272 struct NeedOwnOperatorNew<Eigen::Matrix<Scalar,FixedRows,FixedCols,Options,MaxRows,MaxCols> >
273  : public NeedEigenAlignedOperatorNew { };
274 
276 template<typename Scalar, int FixedRows, int FixedCols, int Options, int MaxRows, int MaxCols>
277 struct NeedOwnOperatorNew<Eigen::Array<Scalar,FixedRows,FixedCols,Options,MaxRows,MaxCols> >
278  : public NeedEigenAlignedOperatorNew { };
279 
280 
281 
282 
283 
284 } // namespace Tools
285 } // namespace Tomographer
286 
287 
288 
289 #endif
Provides correct operator-new implementation for Eigen types via the NeedOwnOperatorNew mechanism...
Base namespace for the Tomographer project.
Definition: densellh.h:45
Provide appropriate operator new() definitions for a structure which has a member of the given stored...
STL class.
Helper to specialize NeedOwnOperatorNew for Eigen types.
Some C++ utilities, with a tad of C++11 tricks.
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
Definition: ezmatio.h:871
Provider for regular types which don&#39;t need any special operator-new implementation (see NeedOwnOpera...