|
20 | 20 | */
|
21 | 21 | #pragma once
|
22 | 22 |
|
| 23 | +#include "openPMD/auxiliary/TypeTraits.hpp" |
| 24 | + |
23 | 25 | #include <array>
|
24 | 26 | #include <climits>
|
25 | 27 | #include <complex>
|
@@ -277,161 +279,62 @@ inline constexpr Datatype determineDatatype()
|
277 | 279 | template <typename T>
|
278 | 280 | inline constexpr Datatype determineDatatype(std::shared_ptr<T>)
|
279 | 281 | {
|
280 |
| - using DT = Datatype; |
281 |
| - if (decay_equiv<T, char>::value) |
282 |
| - { |
283 |
| - return DT::CHAR; |
284 |
| - } |
285 |
| - else if (decay_equiv<T, unsigned char>::value) |
286 |
| - { |
287 |
| - return DT::UCHAR; |
288 |
| - } |
289 |
| - else if (decay_equiv<T, signed char>::value) |
290 |
| - { |
291 |
| - return DT::SCHAR; |
292 |
| - } |
293 |
| - else if (decay_equiv<T, short>::value) |
294 |
| - { |
295 |
| - return DT::SHORT; |
296 |
| - } |
297 |
| - else if (decay_equiv<T, int>::value) |
298 |
| - { |
299 |
| - return DT::INT; |
300 |
| - } |
301 |
| - else if (decay_equiv<T, long>::value) |
302 |
| - { |
303 |
| - return DT::LONG; |
304 |
| - } |
305 |
| - else if (decay_equiv<T, long long>::value) |
306 |
| - { |
307 |
| - return DT::LONGLONG; |
308 |
| - } |
309 |
| - else if (decay_equiv<T, unsigned short>::value) |
310 |
| - { |
311 |
| - return DT::USHORT; |
312 |
| - } |
313 |
| - else if (decay_equiv<T, unsigned int>::value) |
314 |
| - { |
315 |
| - return DT::UINT; |
316 |
| - } |
317 |
| - else if (decay_equiv<T, unsigned long>::value) |
318 |
| - { |
319 |
| - return DT::ULONG; |
320 |
| - } |
321 |
| - else if (decay_equiv<T, unsigned long long>::value) |
322 |
| - { |
323 |
| - return DT::ULONGLONG; |
324 |
| - } |
325 |
| - else if (decay_equiv<T, float>::value) |
326 |
| - { |
327 |
| - return DT::FLOAT; |
328 |
| - } |
329 |
| - else if (decay_equiv<T, double>::value) |
330 |
| - { |
331 |
| - return DT::DOUBLE; |
332 |
| - } |
333 |
| - else if (decay_equiv<T, long double>::value) |
334 |
| - { |
335 |
| - return DT::LONG_DOUBLE; |
336 |
| - } |
337 |
| - else if (decay_equiv<T, std::complex<float>>::value) |
338 |
| - { |
339 |
| - return DT::CFLOAT; |
340 |
| - } |
341 |
| - else if (decay_equiv<T, std::complex<double>>::value) |
342 |
| - { |
343 |
| - return DT::CDOUBLE; |
344 |
| - } |
345 |
| - else if (decay_equiv<T, std::complex<long double>>::value) |
346 |
| - { |
347 |
| - return DT::CLONG_DOUBLE; |
348 |
| - } |
349 |
| - else if (decay_equiv<T, std::string>::value) |
350 |
| - { |
351 |
| - return DT::STRING; |
352 |
| - } |
353 |
| - else if (decay_equiv<T, std::vector<char>>::value) |
354 |
| - { |
355 |
| - return DT::VEC_CHAR; |
356 |
| - } |
357 |
| - else if (decay_equiv<T, std::vector<short>>::value) |
358 |
| - { |
359 |
| - return DT::VEC_SHORT; |
360 |
| - } |
361 |
| - else if (decay_equiv<T, std::vector<int>>::value) |
362 |
| - { |
363 |
| - return DT::VEC_INT; |
364 |
| - } |
365 |
| - else if (decay_equiv<T, std::vector<long>>::value) |
366 |
| - { |
367 |
| - return DT::VEC_LONG; |
368 |
| - } |
369 |
| - else if (decay_equiv<T, std::vector<long long>>::value) |
370 |
| - { |
371 |
| - return DT::VEC_LONGLONG; |
372 |
| - } |
373 |
| - else if (decay_equiv<T, std::vector<unsigned char>>::value) |
374 |
| - { |
375 |
| - return DT::VEC_UCHAR; |
376 |
| - } |
377 |
| - else if (decay_equiv<T, std::vector<signed char>>::value) |
378 |
| - { |
379 |
| - return DT::VEC_SCHAR; |
380 |
| - } |
381 |
| - else if (decay_equiv<T, std::vector<unsigned short>>::value) |
382 |
| - { |
383 |
| - return DT::VEC_USHORT; |
384 |
| - } |
385 |
| - else if (decay_equiv<T, std::vector<unsigned int>>::value) |
386 |
| - { |
387 |
| - return DT::VEC_UINT; |
388 |
| - } |
389 |
| - else if (decay_equiv<T, std::vector<unsigned long>>::value) |
390 |
| - { |
391 |
| - return DT::VEC_ULONG; |
392 |
| - } |
393 |
| - else if (decay_equiv<T, std::vector<unsigned long long>>::value) |
394 |
| - { |
395 |
| - return DT::VEC_ULONGLONG; |
396 |
| - } |
397 |
| - else if (decay_equiv<T, std::vector<float>>::value) |
398 |
| - { |
399 |
| - return DT::VEC_FLOAT; |
400 |
| - } |
401 |
| - else if (decay_equiv<T, std::vector<double>>::value) |
402 |
| - { |
403 |
| - return DT::VEC_DOUBLE; |
404 |
| - } |
405 |
| - else if (decay_equiv<T, std::vector<long double>>::value) |
406 |
| - { |
407 |
| - return DT::VEC_LONG_DOUBLE; |
408 |
| - } |
409 |
| - else if (decay_equiv<T, std::vector<std::complex<float>>>::value) |
410 |
| - { |
411 |
| - return DT::VEC_CFLOAT; |
412 |
| - } |
413 |
| - else if (decay_equiv<T, std::vector<std::complex<double>>>::value) |
414 |
| - { |
415 |
| - return DT::VEC_CDOUBLE; |
416 |
| - } |
417 |
| - else if (decay_equiv<T, std::vector<std::complex<long double>>>::value) |
418 |
| - { |
419 |
| - return DT::VEC_CLONG_DOUBLE; |
420 |
| - } |
421 |
| - else if (decay_equiv<T, std::vector<std::string>>::value) |
422 |
| - { |
423 |
| - return DT::VEC_STRING; |
424 |
| - } |
425 |
| - else if (decay_equiv<T, std::array<double, 7>>::value) |
426 |
| - { |
427 |
| - return DT::ARR_DBL_7; |
| 282 | + return determineDatatype<T>(); |
| 283 | +} |
| 284 | + |
| 285 | +template <typename T> |
| 286 | +inline constexpr Datatype determineDatatype(T *) |
| 287 | +{ |
| 288 | + return determineDatatype<T>(); |
| 289 | +} |
| 290 | + |
| 291 | +/* |
| 292 | + * Catch-all overload for unsupported types, with static_assert errors |
| 293 | + * triggered at compile-time. |
| 294 | + */ |
| 295 | +template <typename T_ContiguousContainer> |
| 296 | +inline constexpr Datatype determineDatatype(T_ContiguousContainer &&) |
| 297 | +{ |
| 298 | + using T_ContiguousContainer_stripped = |
| 299 | + std::remove_reference_t<T_ContiguousContainer>; |
| 300 | + if constexpr (auxiliary::IsContiguousContainer_v< |
| 301 | + T_ContiguousContainer_stripped>) |
| 302 | + { |
| 303 | + static_assert(auxiliary::dependent_false_v<T_ContiguousContainer>, R"( |
| 304 | +Error: Passed a contiguous container type to determineDatatype<>(). |
| 305 | +These types are not directly supported due to colliding semantics. |
| 306 | +Assuming a vector object `std::vector<float> vec;`, |
| 307 | +use one of the following alternatives: |
| 308 | +
|
| 309 | +1) If what you want is a direct openPMD::Datatype equivalent |
| 310 | + of the container type, use: |
| 311 | + `determineDatatype<decltype(vec)>()` |
| 312 | + OR |
| 313 | + `determineDatatype<std::vector<float>>()`. |
| 314 | + The result will be `Datatype::VECTOR_FLOAT`. |
| 315 | +2) If what you want is the openPMD::Datatype equivalent of the *contained type*, |
| 316 | + use the raw pointer overload by: |
| 317 | + `determineDatatype(vec.data())` |
| 318 | + The result will be `Datatype::FLOAT`. |
| 319 | + This is the variant that you likely wish to use if intending to write data |
| 320 | + from the vector via `storeChunk()`, e.g. `storeChunk(vec, {0}, {10})`. |
| 321 | + )"); |
428 | 322 | }
|
429 |
| - else if (decay_equiv<T, bool>::value) |
| 323 | + else |
430 | 324 | {
|
431 |
| - return DT::BOOL; |
| 325 | + static_assert(auxiliary::dependent_false_v<T_ContiguousContainer>, R"( |
| 326 | +Error: Unknown datatype passed to determineDatatype<>(). |
| 327 | +For a direct translation from C++ type to the openPMD::Datatype enum, use: |
| 328 | +`auto determineDatatype<T>() -> Datatype`. |
| 329 | +
|
| 330 | +For detecting the contained datatpye of a pointer type (shared or raw pointer), |
| 331 | +use either of the following overloads: |
| 332 | +`auto determineDatatype<T>(std::shared_ptr<T>) -> Datatype` or |
| 333 | +`auto determineDatatype<T>(T *) -> Datatype`. |
| 334 | + )"); |
432 | 335 | }
|
433 |
| - else |
434 |
| - return DT::UNDEFINED; |
| 336 | + // Unreachable, but C++ does not know it |
| 337 | + return Datatype::UNDEFINED; |
435 | 338 | }
|
436 | 339 |
|
437 | 340 | /** Return number of bytes representing a Datatype
|
|
0 commit comments