Skip to content

Commit

Permalink
Introduce and use switchDatasetType
Browse files Browse the repository at this point in the history
  • Loading branch information
franzpoeschel committed Nov 21, 2023
1 parent e632b33 commit 8469b3d
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 241 deletions.
110 changes: 31 additions & 79 deletions include/openPMD/Datatype.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <array>
#include <climits>
#include <complex>
Expand Down Expand Up @@ -94,85 +98,32 @@ enum class Datatype : int
*/
std::vector<Datatype> 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<float>,
std::complex<double>,
std::complex<long double>>;

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<float>,
std::complex<double>,
std::complex<long double>,
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<float>,
std::complex<double>,
std::complex<long double>,
std::string,
std::vector<char>,
std::vector<short>,
std::vector<int>,
std::vector<long>,
std::vector<long long>,
std::vector<unsigned char>,
std::vector<unsigned short>,
std::vector<unsigned int>,
std::vector<unsigned long>,
std::vector<unsigned long long>,
std::vector<float>,
std::vector<double>,
std::vector<long double>,
std::vector<std::complex<float>>,
std::vector<std::complex<double>>,
std::vector<std::complex<long double>>,
std::vector<signed char>,
std::vector<std::string>,
std::array<double, 7>,
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 <typename Arg, typename... Args>
using variant_tail_t = std::variant<Args...>;
} // namespace detail

using dataset_types =
detail::variant_tail_t<detail::bottom OPENPMD_FOREACH_DATASET_DATATYPE(
OPENPMD_ENUMERATE_TYPES)>;

using non_vector_types =
detail::variant_tail_t<detail::bottom OPENPMD_FOREACH_NONVECTOR_DATATYPE(
OPENPMD_ENUMERATE_TYPES)>;

using attribute_types =
detail::variant_tail_t<detail::bottom OPENPMD_FOREACH_DATATYPE(
OPENPMD_ENUMERATE_TYPES)>;

#undef OPENPMD_ENUMERATE_TYPES

/** @brief Fundamental equivalence check for two given types T and U.
*
Expand Down Expand Up @@ -891,3 +842,4 @@ inline bool operator!=(openPMD::Datatype d, openPMD::Datatype e)
#endif

#include "openPMD/Datatype.tpp"
#include "openPMD/UndefDatatypeMacros.hpp"
196 changes: 49 additions & 147 deletions include/openPMD/Datatype.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <string>
#include <type_traits> // std::void_t
#include <utility> // std::forward
Expand Down Expand Up @@ -83,6 +87,10 @@ namespace detail
};
} // namespace detail

#define OPENPMD_SWITCHTYPE_IMPL(type) \
case determineDatatype<type>(): \
return Action::template call<type>(std::forward<Args>(args)...);

/**
* Generalizes switching over an openPMD datatype.
*
Expand All @@ -105,108 +113,7 @@ constexpr auto switchType(Datatype dt, Args &&...args)
decltype(Action::template call<char>(std::forward<Args>(args)...));
switch (dt)
{
case Datatype::CHAR:
return Action::template call<char>(std::forward<Args>(args)...);
case Datatype::UCHAR:
return Action::template call<unsigned char>(
std::forward<Args>(args)...);
case Datatype::SCHAR:
return Action::template call<signed char>(std::forward<Args>(args)...);
case Datatype::SHORT:
return Action::template call<short>(std::forward<Args>(args)...);
case Datatype::INT:
return Action::template call<int>(std::forward<Args>(args)...);
case Datatype::LONG:
return Action::template call<long>(std::forward<Args>(args)...);
case Datatype::LONGLONG:
return Action::template call<long long>(std::forward<Args>(args)...);
case Datatype::USHORT:
return Action::template call<unsigned short>(
std::forward<Args>(args)...);
case Datatype::UINT:
return Action::template call<unsigned int>(std::forward<Args>(args)...);
case Datatype::ULONG:
return Action::template call<unsigned long>(
std::forward<Args>(args)...);
case Datatype::ULONGLONG:
return Action::template call<unsigned long long>(
std::forward<Args>(args)...);
case Datatype::FLOAT:
return Action::template call<float>(std::forward<Args>(args)...);
case Datatype::DOUBLE:
return Action::template call<double>(std::forward<Args>(args)...);
case Datatype::LONG_DOUBLE:
return Action::template call<long double>(std::forward<Args>(args)...);
case Datatype::CFLOAT:
return Action::template call<std::complex<float>>(
std::forward<Args>(args)...);
case Datatype::CDOUBLE:
return Action::template call<std::complex<double>>(
std::forward<Args>(args)...);
case Datatype::CLONG_DOUBLE:
return Action::template call<std::complex<long double>>(
std::forward<Args>(args)...);
case Datatype::STRING:
return Action::template call<std::string>(std::forward<Args>(args)...);
case Datatype::VEC_CHAR:
return Action::template call<std::vector<char>>(
std::forward<Args>(args)...);
case Datatype::VEC_SHORT:
return Action::template call<std::vector<short>>(
std::forward<Args>(args)...);
case Datatype::VEC_INT:
return Action::template call<std::vector<int>>(
std::forward<Args>(args)...);
case Datatype::VEC_LONG:
return Action::template call<std::vector<long>>(
std::forward<Args>(args)...);
case Datatype::VEC_LONGLONG:
return Action::template call<std::vector<long long>>(
std::forward<Args>(args)...);
case Datatype::VEC_UCHAR:
return Action::template call<std::vector<unsigned char>>(
std::forward<Args>(args)...);
case Datatype::VEC_SCHAR:
return Action::template call<std::vector<signed char>>(
std::forward<Args>(args)...);
case Datatype::VEC_USHORT:
return Action::template call<std::vector<unsigned short>>(
std::forward<Args>(args)...);
case Datatype::VEC_UINT:
return Action::template call<std::vector<unsigned int>>(
std::forward<Args>(args)...);
case Datatype::VEC_ULONG:
return Action::template call<std::vector<unsigned long>>(
std::forward<Args>(args)...);
case Datatype::VEC_ULONGLONG:
return Action::template call<std::vector<unsigned long long>>(
std::forward<Args>(args)...);
case Datatype::VEC_FLOAT:
return Action::template call<std::vector<float>>(
std::forward<Args>(args)...);
case Datatype::VEC_DOUBLE:
return Action::template call<std::vector<double>>(
std::forward<Args>(args)...);
case Datatype::VEC_LONG_DOUBLE:
return Action::template call<std::vector<long double>>(
std::forward<Args>(args)...);
case Datatype::VEC_CFLOAT:
return Action::template call<std::vector<std::complex<float>>>(
std::forward<Args>(args)...);
case Datatype::VEC_CDOUBLE:
return Action::template call<std::vector<std::complex<double>>>(
std::forward<Args>(args)...);
case Datatype::VEC_CLONG_DOUBLE:
return Action::template call<std::vector<std::complex<long double>>>(
std::forward<Args>(args)...);
case Datatype::VEC_STRING:
return Action::template call<std::vector<std::string>>(
std::forward<Args>(args)...);
case Datatype::ARR_DBL_7:
return Action::template call<std::array<double, 7>>(
std::forward<Args>(args)...);
case Datatype::BOOL:
return Action::template call<bool>(std::forward<Args>(args)...);
OPENPMD_FOREACH_DATATYPE(OPENPMD_SWITCHTYPE_IMPL)
case Datatype::UNDEFINED:
return detail::
CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call(
Expand Down Expand Up @@ -241,51 +148,42 @@ constexpr auto switchNonVectorType(Datatype dt, Args &&...args)
decltype(Action::template call<char>(std::forward<Args>(args)...));
switch (dt)
{
case Datatype::CHAR:
return Action::template call<char>(std::forward<Args>(args)...);
case Datatype::UCHAR:
return Action::template call<unsigned char>(
std::forward<Args>(args)...);
case Datatype::SCHAR:
return Action::template call<signed char>(std::forward<Args>(args)...);
case Datatype::SHORT:
return Action::template call<short>(std::forward<Args>(args)...);
case Datatype::INT:
return Action::template call<int>(std::forward<Args>(args)...);
case Datatype::LONG:
return Action::template call<long>(std::forward<Args>(args)...);
case Datatype::LONGLONG:
return Action::template call<long long>(std::forward<Args>(args)...);
case Datatype::USHORT:
return Action::template call<unsigned short>(
std::forward<Args>(args)...);
case Datatype::UINT:
return Action::template call<unsigned int>(std::forward<Args>(args)...);
case Datatype::ULONG:
return Action::template call<unsigned long>(
std::forward<Args>(args)...);
case Datatype::ULONGLONG:
return Action::template call<unsigned long long>(
std::forward<Args>(args)...);
case Datatype::FLOAT:
return Action::template call<float>(std::forward<Args>(args)...);
case Datatype::DOUBLE:
return Action::template call<double>(std::forward<Args>(args)...);
case Datatype::LONG_DOUBLE:
return Action::template call<long double>(std::forward<Args>(args)...);
case Datatype::CFLOAT:
return Action::template call<std::complex<float>>(
std::forward<Args>(args)...);
case Datatype::CDOUBLE:
return Action::template call<std::complex<double>>(
std::forward<Args>(args)...);
case Datatype::CLONG_DOUBLE:
return Action::template call<std::complex<long double>>(
std::forward<Args>(args)...);
case Datatype::STRING:
return Action::template call<std::string>(std::forward<Args>(args)...);
case Datatype::BOOL:
return Action::template call<bool>(std::forward<Args>(args)...);
OPENPMD_FOREACH_NONVECTOR_DATATYPE(OPENPMD_SWITCHTYPE_IMPL)
case Datatype::UNDEFINED:
return detail::
CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call(
std::forward<Args>(args)...);
default:
throw std::runtime_error(
"Internal error: Encountered unknown datatype (switchType) ->" +
std::to_string(static_cast<int>(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 <typename Action, typename... Args>
constexpr auto switchDatasetType(Datatype dt, Args &&...args)
-> decltype(Action::template call<char>(std::forward<Args>(args)...))
{
using ReturnType =
decltype(Action::template call<char>(std::forward<Args>(args)...));
switch (dt)
{
OPENPMD_FOREACH_DATASET_DATATYPE(OPENPMD_SWITCHTYPE_IMPL)
case Datatype::UNDEFINED:
return detail::
CallUndefinedDatatype<0, ReturnType, Action, Args &&...>::call(
Expand All @@ -297,6 +195,8 @@ constexpr auto switchNonVectorType(Datatype dt, Args &&...args)
}
}

#undef OPENPMD_SWITCHTYPE_IMPL

namespace detail
{
template <typename T>
Expand Down Expand Up @@ -354,3 +254,5 @@ constexpr inline bool isSameChar(Datatype d)
return switchType<detail::IsSameChar<T_Char>>(d);
}
} // namespace openPMD

#include "openPMD/UndefDatatypeMacros.hpp"
17 changes: 2 additions & 15 deletions include/openPMD/RecordComponent.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,20 +383,7 @@ namespace detail
template <typename T, typename... Args>
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<T, std::string> || std::is_same_v<T, bool>)
{
throw std::runtime_error(
"[RecordComponent::visit()] Unsupported datatype in "
"RecordComponent");
}
else
{
return Functor::template call<T>(
rc, std::forward<Args>(args)...);
}
return Functor::template call<T>(rc, std::forward<Args>(args)...);
}

template <int = 0, typename... Args>
Expand All @@ -416,7 +403,7 @@ constexpr auto RecordComponent::visit(Args &&...args)
{
using Res = decltype(Visitor::template call<char>(
std::declval<RecordComponent &>(), std::forward<Args>(args)...));
return switchNonVectorType<detail::VisitRecordComponent<Visitor, Res>>(
return switchDatasetType<detail::VisitRecordComponent<Visitor, Res>>(
getDatatype(), *this, std::forward<Args>(args)...);
}

Expand Down

0 comments on commit 8469b3d

Please sign in to comment.