From 8469b3d7b90ef478217f6330cd1e7bd056d7acc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20P=C3=B6schel?= Date: Thu, 9 Nov 2023 14:46:49 +0100 Subject: [PATCH] Introduce and use switchDatasetType --- include/openPMD/Datatype.hpp | 110 +++++----------- include/openPMD/Datatype.tpp | 196 +++++++--------------------- include/openPMD/RecordComponent.tpp | 17 +-- 3 files changed, 82 insertions(+), 241 deletions(-) diff --git a/include/openPMD/Datatype.hpp b/include/openPMD/Datatype.hpp index bce9f461ca..0772df1d83 100644 --- a/include/openPMD/Datatype.hpp +++ b/include/openPMD/Datatype.hpp @@ -23,6 +23,10 @@ #include "openPMD/auxiliary/TypeTraits.hpp" #include "openPMD/auxiliary/UniquePtr.hpp" +// comment to prevent clang-format from moving this #include up +// datatype macros may be included and un-included in other headers +#include "openPMD/DatatypeMacros.hpp" + #include #include #include @@ -94,85 +98,32 @@ enum class Datatype : int */ std::vector openPMD_Datatypes(); -using dataset_types = std::variant< - char, - unsigned char, - signed char, - short, - int, - long, - long long, - unsigned short, - unsigned int, - unsigned long, - unsigned long long, - float, - double, - long double, - std::complex, - std::complex, - std::complex>; - -using non_vector_types = std::variant< - char, - unsigned char, - signed char, - short, - int, - long, - long long, - unsigned short, - unsigned int, - unsigned long, - unsigned long long, - float, - double, - long double, - std::complex, - std::complex, - std::complex, - std::string, - bool>; - -using attribute_types = std::variant< - char, - unsigned char, - signed char, - short, - int, - long, - long long, - unsigned short, - unsigned int, - unsigned long, - unsigned long long, - float, - double, - long double, - std::complex, - std::complex, - std::complex, - std::string, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector, - std::vector>, - std::vector>, - std::vector>, - std::vector, - std::vector, - std::array, - bool>; +#define OPENPMD_ENUMERATE_TYPES(type) , type + +namespace detail +{ + struct bottom + {}; + + // std::variant, but ignore first template parameter + // little trick to avoid trailing commas in the macro expansions below + template + using variant_tail_t = std::variant; +} // namespace detail + +using dataset_types = + detail::variant_tail_t; + +using non_vector_types = + detail::variant_tail_t; + +using attribute_types = + detail::variant_tail_t; + +#undef OPENPMD_ENUMERATE_TYPES /** @brief Fundamental equivalence check for two given types T and U. * @@ -891,3 +842,4 @@ inline bool operator!=(openPMD::Datatype d, openPMD::Datatype e) #endif #include "openPMD/Datatype.tpp" +#include "openPMD/UndefDatatypeMacros.hpp" diff --git a/include/openPMD/Datatype.tpp b/include/openPMD/Datatype.tpp index 64d6d30d5b..6685c62f73 100644 --- a/include/openPMD/Datatype.tpp +++ b/include/openPMD/Datatype.tpp @@ -22,6 +22,10 @@ #include "openPMD/Datatype.hpp" +// comment to prevent clang-format from moving this #include up +// datatype macros may be included and un-included in other headers +#include "openPMD/DatatypeMacros.hpp" + #include #include // std::void_t #include // std::forward @@ -83,6 +87,10 @@ namespace detail }; } // namespace detail +#define OPENPMD_SWITCHTYPE_IMPL(type) \ + case determineDatatype(): \ + return Action::template call(std::forward(args)...); + /** * Generalizes switching over an openPMD datatype. * @@ -105,108 +113,7 @@ constexpr auto switchType(Datatype dt, Args &&...args) decltype(Action::template call(std::forward(args)...)); switch (dt) { - case Datatype::CHAR: - return Action::template call(std::forward(args)...); - case Datatype::UCHAR: - return Action::template call( - std::forward(args)...); - case Datatype::SCHAR: - return Action::template call(std::forward(args)...); - case Datatype::SHORT: - return Action::template call(std::forward(args)...); - case Datatype::INT: - return Action::template call(std::forward(args)...); - case Datatype::LONG: - return Action::template call(std::forward(args)...); - case Datatype::LONGLONG: - return Action::template call(std::forward(args)...); - case Datatype::USHORT: - return Action::template call( - std::forward(args)...); - case Datatype::UINT: - return Action::template call(std::forward(args)...); - case Datatype::ULONG: - return Action::template call( - std::forward(args)...); - case Datatype::ULONGLONG: - return Action::template call( - std::forward(args)...); - case Datatype::FLOAT: - return Action::template call(std::forward(args)...); - case Datatype::DOUBLE: - return Action::template call(std::forward(args)...); - case Datatype::LONG_DOUBLE: - return Action::template call(std::forward(args)...); - case Datatype::CFLOAT: - return Action::template call>( - std::forward(args)...); - case Datatype::CDOUBLE: - return Action::template call>( - std::forward(args)...); - case Datatype::CLONG_DOUBLE: - return Action::template call>( - std::forward(args)...); - case Datatype::STRING: - return Action::template call(std::forward(args)...); - case Datatype::VEC_CHAR: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_SHORT: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_INT: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_LONG: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_LONGLONG: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_UCHAR: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_SCHAR: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_USHORT: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_UINT: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_ULONG: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_ULONGLONG: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_FLOAT: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_DOUBLE: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_LONG_DOUBLE: - return Action::template call>( - std::forward(args)...); - case Datatype::VEC_CFLOAT: - return Action::template call>>( - std::forward(args)...); - case Datatype::VEC_CDOUBLE: - return Action::template call>>( - std::forward(args)...); - case Datatype::VEC_CLONG_DOUBLE: - return Action::template call>>( - std::forward(args)...); - case Datatype::VEC_STRING: - return Action::template call>( - std::forward(args)...); - case Datatype::ARR_DBL_7: - return Action::template call>( - std::forward(args)...); - case Datatype::BOOL: - return Action::template call(std::forward(args)...); + OPENPMD_FOREACH_DATATYPE(OPENPMD_SWITCHTYPE_IMPL) case Datatype::UNDEFINED: return detail:: CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call( @@ -241,51 +148,42 @@ constexpr auto switchNonVectorType(Datatype dt, Args &&...args) decltype(Action::template call(std::forward(args)...)); switch (dt) { - case Datatype::CHAR: - return Action::template call(std::forward(args)...); - case Datatype::UCHAR: - return Action::template call( - std::forward(args)...); - case Datatype::SCHAR: - return Action::template call(std::forward(args)...); - case Datatype::SHORT: - return Action::template call(std::forward(args)...); - case Datatype::INT: - return Action::template call(std::forward(args)...); - case Datatype::LONG: - return Action::template call(std::forward(args)...); - case Datatype::LONGLONG: - return Action::template call(std::forward(args)...); - case Datatype::USHORT: - return Action::template call( - std::forward(args)...); - case Datatype::UINT: - return Action::template call(std::forward(args)...); - case Datatype::ULONG: - return Action::template call( - std::forward(args)...); - case Datatype::ULONGLONG: - return Action::template call( - std::forward(args)...); - case Datatype::FLOAT: - return Action::template call(std::forward(args)...); - case Datatype::DOUBLE: - return Action::template call(std::forward(args)...); - case Datatype::LONG_DOUBLE: - return Action::template call(std::forward(args)...); - case Datatype::CFLOAT: - return Action::template call>( - std::forward(args)...); - case Datatype::CDOUBLE: - return Action::template call>( - std::forward(args)...); - case Datatype::CLONG_DOUBLE: - return Action::template call>( - std::forward(args)...); - case Datatype::STRING: - return Action::template call(std::forward(args)...); - case Datatype::BOOL: - return Action::template call(std::forward(args)...); + OPENPMD_FOREACH_NONVECTOR_DATATYPE(OPENPMD_SWITCHTYPE_IMPL) + case Datatype::UNDEFINED: + return detail:: + CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call( + std::forward(args)...); + default: + throw std::runtime_error( + "Internal error: Encountered unknown datatype (switchType) ->" + + std::to_string(static_cast(dt))); + } +} + +/** + * Generalizes switching over an openPMD datatype. + * + * Will call the function template found at Action::call< T >(), instantiating T + * with the C++ internal datatype corresponding to the openPMD datatype. + * Specializes only on those types that can occur in a dataset. + * + * @tparam ReturnType The function template's return type. + * @tparam Action The struct containing the function template. + * @tparam Args The function template's argument types. + * @param dt The openPMD datatype. + * @param args The function template's arguments. + * @return Passes on the result of invoking the function template with the given + * arguments and with the template parameter specified by dt. + */ +template +constexpr auto switchDatasetType(Datatype dt, Args &&...args) + -> decltype(Action::template call(std::forward(args)...)) +{ + using ReturnType = + decltype(Action::template call(std::forward(args)...)); + switch (dt) + { + OPENPMD_FOREACH_DATASET_DATATYPE(OPENPMD_SWITCHTYPE_IMPL) case Datatype::UNDEFINED: return detail:: CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call( @@ -297,6 +195,8 @@ constexpr auto switchNonVectorType(Datatype dt, Args &&...args) } } +#undef OPENPMD_SWITCHTYPE_IMPL + namespace detail { template @@ -354,3 +254,5 @@ constexpr inline bool isSameChar(Datatype d) return switchType>(d); } } // namespace openPMD + +#include "openPMD/UndefDatatypeMacros.hpp" diff --git a/include/openPMD/RecordComponent.tpp b/include/openPMD/RecordComponent.tpp index 122314df55..e34013327f 100644 --- a/include/openPMD/RecordComponent.tpp +++ b/include/openPMD/RecordComponent.tpp @@ -383,20 +383,7 @@ namespace detail template static Res call(RecordComponent &rc, Args &&...args) { - // Need to filter these out as they are part of - // switchNonVectorType, but not allowed in datasets - if constexpr ( - std::is_same_v || std::is_same_v) - { - throw std::runtime_error( - "[RecordComponent::visit()] Unsupported datatype in " - "RecordComponent"); - } - else - { - return Functor::template call( - rc, std::forward(args)...); - } + return Functor::template call(rc, std::forward(args)...); } template @@ -416,7 +403,7 @@ constexpr auto RecordComponent::visit(Args &&...args) { using Res = decltype(Visitor::template call( std::declval(), std::forward(args)...)); - return switchNonVectorType>( + return switchDatasetType>( getDatatype(), *this, std::forward(args)...); }