Tomographer  v5.3
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 
53 struct TOMOGRAPHER_EXPORT NoSpecialOperatorNewProvider {
54  template<typename T>
56 };
57 
59 struct TOMOGRAPHER_EXPORT NoSpecialOperatorNew {
61 
62  // prevent inadvertently inheriting this class instead of
63  // NoSpecialOperatorNewProvider:
64  NoSpecialOperatorNew() = delete;
65 };
66 
67 
68 namespace tomo_internal {
69 
70 // see http://stackoverflow.com/a/9154394/1694896
71 template<typename T> static auto test_has_ownopnewprovidertype_member(int)
72  -> typename sfinae_yes<typename T::OperatorNewProviderType>::yes&;
73 template<typename T> static auto test_has_ownopnewprovidertype_member(long)
74  -> typename sfinae_no<>::no&;
75 template<typename T>
76 struct has_ownopnewprovidertype_member {
77  static constexpr bool value = (sizeof(tomo_internal::test_has_ownopnewprovidertype_member<T>(0))
78  == sizeof(typename tomo_internal::sfinae_yes<>::yes));
79 };
80 template<bool has_own_provider, typename T>
81 struct need_own_op_new_prov_helper {
83 };
84 template<typename T>
85 struct need_own_op_new_prov_helper<true, T> {
86  typedef typename T::OperatorNewProviderType ProviderType;
87 };
88 } // namespace tomo_internal
89 
90 
144 template<typename... Types>
146  // will be specialized appropriately.
147 };
148 
149 
153 template<typename T>
155  typedef typename tomo_internal::need_own_op_new_prov_helper<
157  T
159  ProviderType;
160 
161  typedef typename ProviderType::template OperatorNewAllocatorType<T>::Type AllocatorType;
162 };
163 
164 
165 //
166 // Dark magic for allowing a struct to have several members of possibly different struct
167 // types (such as a ValueCalculator and a HistogramTypes), each of which might possibly
168 // require their own operator-new-providers; those super-structures should inherit from
169 // NeedOwnOperatorNew<Type1,Type2,Type3,...>::ProviderType , which resolves to the
170 // provider-type of all these types if they are the same (or if they don't require a
171 // provider-type).
172 //
173 
174 template<typename Type1, typename Type2, typename... OtherTypes>
175 struct NeedOwnOperatorNew<Type1, Type2, OtherTypes...>;
176 
177 
178 namespace tomo_internal {
179 
180 template<bool same_provider_type, bool t1_trivial_provider, bool t2_trivial_provider,
181  typename Type1, typename Type2, typename... OtherTypes>
182 struct need_own_operator_new_combination_helper {
183  // missing ProviderType member, will generate runtime error.
184  static_assert(!same_provider_type && !t1_trivial_provider && !t2_trivial_provider,
185  "ERROR: you have a type which requested a NeedOwnOperatorNew<T1,T2> "
186  "with incompatible needs.") ;
187 };
188 // case same_provider_type == true
189 template<bool t1_trivial_provider, bool t2_trivial_provider,
190  typename Type1, typename Type2, typename... OtherTypes>
191 struct need_own_operator_new_combination_helper<true, t1_trivial_provider, t2_trivial_provider,
192  Type1, Type2, OtherTypes...> {
193  // Type1 and Type2 have same provider, all ok, so continue and recurse on the other types:
194  typedef typename NeedOwnOperatorNew<Type1, OtherTypes...>::ProviderType ProviderType;
195 };
196 // case t1_trivial_provider == true
197 template<bool t2_trivial_provider,
198  typename Type1, typename Type2, typename... OtherTypes>
199 struct need_own_operator_new_combination_helper<false, true, t2_trivial_provider,
200  Type1, Type2, OtherTypes...> {
201  // all ok, use Type2's provider, and recurse on the other types
202  typedef typename NeedOwnOperatorNew<Type2, OtherTypes...>::ProviderType ProviderType;
203 };
204 // case t2_trivial_provider == true (and t1_trivial_provider == false, otherwise see case above)
205 template<typename Type1, typename Type2, typename... OtherTypes>
206 struct need_own_operator_new_combination_helper<false, false, true,
207  Type1, Type2, OtherTypes...> {
208  // all ok, use Type2's provider, and recurse on the other types
209  typedef typename NeedOwnOperatorNew<Type1, OtherTypes...>::ProviderType ProviderType;
210 };
211 
212 
213 } // namespace tomo_internal
214 
215 
216 template<typename Type1, typename Type2, typename... OtherTypes>
217 struct NeedOwnOperatorNew<Type1, Type2, OtherTypes...>
218 {
219  typedef tomo_internal::need_own_operator_new_combination_helper<
222  std::is_same<typename NeedOwnOperatorNew<Type1>::ProviderType,
226  Type1, Type2, OtherTypes...
227  > ProviderType;
228 };
229 
230 
231 
232 
233 
234 
235 
236 
237 //
238 // for Eigen types
239 //
240 
241 
242 
246 struct TOMOGRAPHER_EXPORT EigenAlignedOperatorNewProvider {
247 public:
248  EIGEN_MAKE_ALIGNED_OPERATOR_NEW ;
250 
251  template<typename T> struct OperatorNewAllocatorType {
253  };
254 
255 #ifdef TOMOGRAPHER_TEST_TOOLS_NEEDOWNOPERATORNEW_DEBUG_MEMBERS
256  // DEBUG: provide something we can test that it is indeed eigen-aligned
258  : EigenAlignedOperatorNewIsActive(true)
259  {
260  }
261  const bool EigenAlignedOperatorNewIsActive;
262 #endif
263 };
264 
265 
267 template<bool ReallyNeeded = true>
270 
271  // prevent inadvertently inheriting this class instead of
272  // EigenAlignedOperatorNewProvider:
273  NeedEigenAlignedOperatorNew() = delete;
274 };
275 // but if it's not really needed, for instance for dynamic-sized Eigen matrices which
276 // anyway allocate the data on the heap internally using aligned allocators:
277 template<>
280 
281  // prevent inadvertently inheriting this class instead of
282  // EigenAlignedOperatorNewProvider:
283  NeedEigenAlignedOperatorNew() = delete;
284 };
285 
290 template<typename Scalar, int FixedRows, int FixedCols, int Options, int MaxRows, int MaxCols>
291 struct NeedOwnOperatorNew<Eigen::Matrix<Scalar,FixedRows,FixedCols,Options,MaxRows,MaxCols> >
292  : public NeedEigenAlignedOperatorNew<!(MaxRows == Eigen::Dynamic || MaxCols == Eigen::Dynamic)> { };
293 
294 
296 template<typename Scalar, int FixedRows, int FixedCols, int Options, int MaxRows, int MaxCols>
297 struct NeedOwnOperatorNew<Eigen::Array<Scalar,FixedRows,FixedCols,Options,MaxRows,MaxCols> >
298  : public NeedEigenAlignedOperatorNew<!(MaxRows == Eigen::Dynamic || MaxCols == Eigen::Dynamic)> { };
299 
300 
301 
302 
303 
304 } // namespace Tools
305 } // namespace Tomographer
306 
307 
308 
309 #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 for NoSpecialOperatorNewProvider.
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:878
Provider for regular types which don&#39;t need any special operator-new implementation (see NeedOwnOpera...