openPMD-api
DatatypeHelpers.hpp
1 /* Copyright 2017-2021 Fabian Koller, Franz Poeschel, Axel Huebl
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 #pragma once
22 
23 #include "openPMD/Datatype.hpp"
24 
25 #include <string>
26 #include <type_traits>
27 #include <utility> // std::forward
28 
29 namespace openPMD
30 {
31 
32 #if defined( _MSC_VER ) && !defined( __INTEL_COMPILER ) && !defined( __clang__ )
33 #define OPENPMD_TEMPLATE_OPERATOR operator
34 #else
35 #define OPENPMD_TEMPLATE_OPERATOR template operator
36 #endif
37 
38 namespace detail
39 {
40 // std::void_t is C++17
41 template< typename >
42 using void_t = void;
43 
44 /*
45  * Check whether class T has a member "errorMsg" convertible
46  * to type std::string.
47  * Used to give helpful compile-time error messages with static_assert
48  * down in CallUndefinedDatatype.
49  */
50 template< typename T, typename = void >
52 {
53  static constexpr bool value = false;
54 };
55 
56 template< typename T >
58  T,
59  void_t< decltype( std::string( std::declval< T >().errorMsg ) ) > >
60 {
61  static constexpr bool value = true;
62 };
63 
76 template<
77  int n,
78  typename ReturnType,
79  typename Action,
80  typename Placeholder,
81  typename... Args >
83 {
84  static ReturnType call( Action action, Args &&... )
85  {
86  static_assert(
88  "[switchType] Action needs either an errorMsg member of type "
89  "std::string or operator()<unsigned>() overloads." );
90  throw std::runtime_error(
91  "[" + std::string( action.errorMsg ) + "] Unknown Datatype." );
92  }
93 };
94 
95 template< int n, typename ReturnType, typename Action, typename... Args >
97  n,
98  ReturnType,
99  Action,
100  // Enable this, if no error message member is found.
101  // action.template operator()<n>() will be called instead
102  typename std::enable_if< !HasErrorMessageMember< Action >::value >::type,
103  Args... >
104 {
105  static ReturnType call( Action action, Args &&... args )
106  {
107  return action.OPENPMD_TEMPLATE_OPERATOR()< n >(
108  std::forward< Args >( args )... );
109  }
110 };
111 }
112 
130 template< typename Action, typename... Args >
131 auto switchType( Datatype dt, Action action, Args &&... args ) -> decltype(
132  action.OPENPMD_TEMPLATE_OPERATOR() < char >
133  ( std::forward< Args >( args )... ) )
134 {
135  using ReturnType = decltype(
136  action.OPENPMD_TEMPLATE_OPERATOR() < char >
137  ( std::forward< Args >( args )... ) );
138  switch( dt )
139  {
140  case Datatype::CHAR:
141  return action.OPENPMD_TEMPLATE_OPERATOR()< char >(
142  std::forward< Args >( args )... );
143  case Datatype::UCHAR:
144  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned char >(
145  std::forward< Args >( args )... );
146  case Datatype::SHORT:
147  return action.OPENPMD_TEMPLATE_OPERATOR()< short >(
148  std::forward< Args >( args )... );
149  case Datatype::INT:
150  return action.OPENPMD_TEMPLATE_OPERATOR()< int >(
151  std::forward< Args >( args )... );
152  case Datatype::LONG:
153  return action.OPENPMD_TEMPLATE_OPERATOR()< long >(
154  std::forward< Args >( args )... );
155  case Datatype::LONGLONG:
156  return action.OPENPMD_TEMPLATE_OPERATOR()< long long >(
157  std::forward< Args >( args )... );
158  case Datatype::USHORT:
159  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned short >(
160  std::forward< Args >( args )... );
161  case Datatype::UINT:
162  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned int >(
163  std::forward< Args >( args )... );
164  case Datatype::ULONG:
165  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long >(
166  std::forward< Args >( args )... );
167  case Datatype::ULONGLONG:
168  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long long >(
169  std::forward< Args >( args )... );
170  case Datatype::FLOAT:
171  return action.OPENPMD_TEMPLATE_OPERATOR()< float >(
172  std::forward< Args >( args )... );
173  case Datatype::DOUBLE:
174  return action.OPENPMD_TEMPLATE_OPERATOR()< double >(
175  std::forward< Args >( args )... );
176  case Datatype::LONG_DOUBLE:
177  return action.OPENPMD_TEMPLATE_OPERATOR()< long double >(
178  std::forward< Args >( args )... );
179  case Datatype::CFLOAT:
180  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< float > >(
181  std::forward< Args >( args )... );
182  case Datatype::CDOUBLE:
183  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< double > >(
184  std::forward< Args >( args )... );
185  case Datatype::CLONG_DOUBLE:
186  return action
187  .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
188  std::forward< Args >( args )... );
189  case Datatype::STRING:
190  return action.OPENPMD_TEMPLATE_OPERATOR()< std::string >(
191  std::forward< Args >( args )... );
192  case Datatype::VEC_CHAR:
193  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< char > >(
194  std::forward< Args >( args )... );
195  case Datatype::VEC_SHORT:
196  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< short > >(
197  std::forward< Args >( args )... );
198  case Datatype::VEC_INT:
199  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< int > >(
200  std::forward< Args >( args )... );
201  case Datatype::VEC_LONG:
202  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< long > >(
203  std::forward< Args >( args )... );
204  case Datatype::VEC_LONGLONG:
205  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< long long > >(
206  std::forward< Args >( args )... );
207  case Datatype::VEC_UCHAR:
208  return action
209  .OPENPMD_TEMPLATE_OPERATOR()< std::vector< unsigned char > >(
210  std::forward< Args >( args )... );
211  case Datatype::VEC_USHORT:
212  return action
213  .OPENPMD_TEMPLATE_OPERATOR()< std::vector< unsigned short > >(
214  std::forward< Args >( args )... );
215  case Datatype::VEC_UINT:
216  return action
217  .OPENPMD_TEMPLATE_OPERATOR()< std::vector< unsigned int > >(
218  std::forward< Args >( args )... );
219  case Datatype::VEC_ULONG:
220  return action
221  .OPENPMD_TEMPLATE_OPERATOR()< std::vector< unsigned long > >(
222  std::forward< Args >( args )... );
223  case Datatype::VEC_ULONGLONG:
224  return action
225  .OPENPMD_TEMPLATE_OPERATOR()< std::vector< unsigned long long > >(
226  std::forward< Args >( args )... );
227  case Datatype::VEC_FLOAT:
228  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< float > >(
229  std::forward< Args >( args )... );
230  case Datatype::VEC_DOUBLE:
231  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< double > >(
232  std::forward< Args >( args )... );
233  case Datatype::VEC_LONG_DOUBLE:
234  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< long double > >(
235  std::forward< Args >( args )... );
236  case Datatype::VEC_CFLOAT:
237  return action.OPENPMD_TEMPLATE_OPERATOR()<
238  std::vector< std::complex< float > > >(
239  std::forward< Args >( args )... );
240  case Datatype::VEC_CDOUBLE:
241  return action.OPENPMD_TEMPLATE_OPERATOR()<
242  std::vector< std::complex< double > > >(
243  std::forward< Args >( args )... );
244  case Datatype::VEC_CLONG_DOUBLE:
245  return action.OPENPMD_TEMPLATE_OPERATOR()<
246  std::vector< std::complex< long double > > >(
247  std::forward< Args >( args )... );
248  case Datatype::VEC_STRING:
249  return action.OPENPMD_TEMPLATE_OPERATOR()< std::vector< std::string > >(
250  std::forward< Args >( args )... );
251  case Datatype::ARR_DBL_7:
252  return action.OPENPMD_TEMPLATE_OPERATOR()< std::array< double, 7 > >(
253  std::forward< Args >( args )... );
254  case Datatype::BOOL:
255  return action.OPENPMD_TEMPLATE_OPERATOR()< bool >(
256  std::forward< Args >( args )... );
257  case Datatype::DATATYPE:
259  HIGHEST_DATATYPE,
260  ReturnType,
261  Action,
262  void,
263  Args &&... >::
264  call( std::move( action ), std::forward< Args >( args )... );
265  case Datatype::UNDEFINED:
267  LOWEST_DATATYPE,
268  ReturnType,
269  Action,
270  void,
271  Args &&... >::
272  call( std::move( action ), std::forward< Args >( args )... );
273  default:
274  throw std::runtime_error(
275  "Internal error: Encountered unknown datatype (switchType) ->" +
276  std::to_string( static_cast< int >( dt ) ) );
277  }
278 }
279 
298 template< typename Action, typename... Args >
299 auto switchNonVectorType( Datatype dt, Action action, Args &&... args )
300  -> decltype(
301  action.OPENPMD_TEMPLATE_OPERATOR() < char >
302  ( std::forward< Args >( args )... ) )
303 {
304  using ReturnType = decltype(
305  action.OPENPMD_TEMPLATE_OPERATOR() < char >
306  ( std::forward< Args >( args )... ) );
307  switch( dt )
308  {
309  case Datatype::CHAR:
310  return action.OPENPMD_TEMPLATE_OPERATOR()< char >(
311  std::forward< Args >( args )... );
312  case Datatype::UCHAR:
313  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned char >(
314  std::forward< Args >( args )... );
315  case Datatype::SHORT:
316  return action.OPENPMD_TEMPLATE_OPERATOR()< short >(
317  std::forward< Args >( args )... );
318  case Datatype::INT:
319  return action.OPENPMD_TEMPLATE_OPERATOR()< int >(
320  std::forward< Args >( args )... );
321  case Datatype::LONG:
322  return action.OPENPMD_TEMPLATE_OPERATOR()< long >(
323  std::forward< Args >( args )... );
324  case Datatype::LONGLONG:
325  return action.OPENPMD_TEMPLATE_OPERATOR()< long long >(
326  std::forward< Args >( args )... );
327  case Datatype::USHORT:
328  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned short >(
329  std::forward< Args >( args )... );
330  case Datatype::UINT:
331  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned int >(
332  std::forward< Args >( args )... );
333  case Datatype::ULONG:
334  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long >(
335  std::forward< Args >( args )... );
336  case Datatype::ULONGLONG:
337  return action.OPENPMD_TEMPLATE_OPERATOR()< unsigned long long >(
338  std::forward< Args >( args )... );
339  case Datatype::FLOAT:
340  return action.OPENPMD_TEMPLATE_OPERATOR()< float >(
341  std::forward< Args >( args )... );
342  case Datatype::DOUBLE:
343  return action.OPENPMD_TEMPLATE_OPERATOR()< double >(
344  std::forward< Args >( args )... );
345  case Datatype::LONG_DOUBLE:
346  return action.OPENPMD_TEMPLATE_OPERATOR()< long double >(
347  std::forward< Args >( args )... );
348  case Datatype::CFLOAT:
349  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< float > >(
350  std::forward< Args >( args )... );
351  case Datatype::CDOUBLE:
352  return action.OPENPMD_TEMPLATE_OPERATOR()< std::complex< double > >(
353  std::forward< Args >( args )... );
354  case Datatype::CLONG_DOUBLE:
355  return action
356  .OPENPMD_TEMPLATE_OPERATOR()< std::complex< long double > >(
357  std::forward< Args >( args )... );
358  case Datatype::STRING:
359  return action.OPENPMD_TEMPLATE_OPERATOR()< std::string >(
360  std::forward< Args >( args )... );
361  case Datatype::BOOL:
362  return action.OPENPMD_TEMPLATE_OPERATOR()< bool >(
363  std::forward< Args >( args )... );
364  case Datatype::DATATYPE:
366  HIGHEST_DATATYPE,
367  ReturnType,
368  Action,
369  void,
370  Args &&... >::
371  call( std::move( action ), std::forward< Args >( args )... );
372  case Datatype::UNDEFINED:
374  LOWEST_DATATYPE,
375  ReturnType,
376  Action,
377  void,
378  Args &&... >::
379  call( std::move( action ), std::forward< Args >( args )... );
380  default:
381  throw std::runtime_error(
382  "Internal error: Encountered unknown datatype (switchType) ->" +
383  std::to_string( static_cast< int >( dt ) ) );
384  }
385 }
386 #undef OPENPMD_TEMPLATE_OPERATOR
387 }
auto switchType(Datatype dt, Action action, Args &&... args) -> decltype(action. template operator()< char >(std::forward< Args >(args)...))
Generalizes switching over an openPMD datatype.
Definition: DatatypeHelpers.hpp:131
Purpose of this struct is to detect at compile time whether Action::template operator()<0>() exists...
Definition: DatatypeHelpers.hpp:82
auto switchNonVectorType(Datatype dt, Action action, Args &&... args) -> decltype(action. template operator()< char >(std::forward< Args >(args)...))
Generalizes switching over an openPMD datatype.
Definition: DatatypeHelpers.hpp:299
STL namespace.
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:45
Definition: Container.cpp:51
Definition: DatatypeHelpers.hpp:51
Public definitions of openPMD-api.
Definition: Date.cpp:29