|
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