23 #include "openPMD/Datatype.hpp"
24 #include "openPMD/auxiliary/TypeTraits.hpp"
25 #include "openPMD/auxiliary/Variant.hpp"
29 #include "openPMD/DatatypeMacros.hpp"
39 #include <type_traits>
56 #define OPENPMD_ENUMERATE_TYPES(type) , type
60 OPENPMD_ENUMERATE_TYPES)>
62 #undef OPENPMD_ENUMERATE_TYPES
80 #define OPENPMD_ATTRIBUTE_CONSTRUCTOR_FROM_VARIANT(TYPE) \
81 Attribute(TYPE val) : Variant(Variant::from_basic_type, std::move(val)) \
84 OPENPMD_FOREACH_DATATYPE(OPENPMD_ATTRIBUTE_CONSTRUCTOR_FROM_VARIANT)
86 #undef OPENPMD_ATTRIBUTE_CONSTRUCTOR_FROM_VARIANT
89 : Variant(Variant::from_any, std::move(val))
101 template <
typename U>
115 template <
typename U>
130 template <
typename U>
142 [[nodiscard]] std::variant<Attribute, std::runtime_error>
152 [[nodiscard]] std::variant<Attribute, std::runtime_error>
158 template <
typename T,
typename U>
159 auto doConvert(T
const *pv) -> std::variant<U, std::runtime_error>
162 if constexpr (std::is_convertible_v<T, U>)
164 return {
static_cast<U
>(*pv)};
167 std::is_same_v<T, std::string> && auxiliary::IsChar_v<U>)
171 return static_cast<U
>(pv->at(0));
175 return {std::runtime_error(
176 "getCast: cast from string to char only "
177 "possible if string has length 1.")};
181 auxiliary::IsChar_v<T> && std::is_same_v<U, std::string>)
183 return std::string(1, *pv);
185 else if constexpr (auxiliary::IsVector_v<T> && auxiliary::IsVector_v<U>)
188 res.reserve(pv->size());
190 std::is_convertible_v<
191 typename T::value_type,
192 typename U::value_type>)
194 std::copy(pv->begin(), pv->end(), std::back_inserter(res));
200 for (
auto const &val : *pv)
202 auto conv = doConvert<
203 typename T::value_type,
204 typename U::value_type>(&val);
206 std::get_if<typename U::value_type>(&conv);
209 res.push_back(std::move(*conv_val));
213 auto exception = std::get<std::runtime_error>(conv);
214 return {std::runtime_error(
216 "getCast: no vector cast possible, recursive "
227 else if constexpr (auxiliary::IsArray_v<T> && auxiliary::IsVector_v<U>)
230 res.reserve(pv->size());
232 std::is_convertible_v<
233 typename T::value_type,
234 typename U::value_type>)
236 std::copy(pv->begin(), pv->end(), std::back_inserter(res));
242 for (
auto const &val : *pv)
244 auto conv = doConvert<
245 typename T::value_type,
246 typename U::value_type>(&val);
248 std::get_if<typename U::value_type>(&conv);
251 res.push_back(std::move(*conv_val));
255 auto exception = std::get<std::runtime_error>(conv);
256 return {std::runtime_error(
258 "getCast: no array to vector conversion "
259 "possible, recursive error: ") +
269 else if constexpr (auxiliary::IsVector_v<T> && auxiliary::IsArray_v<U>)
273 std::is_convertible_v<
274 typename T::value_type,
275 typename U::value_type>)
277 if (res.size() != pv->size())
279 return std::runtime_error(
280 "getCast: no vector to array conversion possible "
282 "requested array size).");
284 for (
size_t i = 0; i < res.size(); ++i)
286 res[i] =
static_cast<typename U::value_type
>((*pv)[i]);
293 for (
size_t i = 0; i <= res.size(); ++i)
295 auto const &val = (*pv)[i];
296 auto conv = doConvert<
297 typename T::value_type,
298 typename U::value_type>(&val);
300 std::get_if<typename U::value_type>(&conv);
303 res[i] = std::move(*conv_val);
307 auto exception = std::get<std::runtime_error>(conv);
308 return {std::runtime_error(
310 "getCast: no vector to array conversion "
311 "possible, recursive error: ") +
319 else if constexpr (auxiliary::IsVector_v<U>)
323 if constexpr (std::is_convertible_v<T, typename U::value_type>)
325 res.push_back(
static_cast<typename U::value_type
>(*pv));
331 auto conv = doConvert<T, typename U::value_type>(pv);
332 if (
auto conv_val = std::get_if<typename U::value_type>(&conv);
335 res.push_back(std::move(*conv_val));
340 auto exception = std::get<std::runtime_error>(conv);
341 return {std::runtime_error(
343 "getCast: no scalar to vector conversion "
344 "possible, recursive error: ") +
351 return {std::runtime_error(
"getCast: no cast possible.")};
353 #if defined(__INTEL_COMPILER)
361 #pragma warning(disable : 1011)
363 #pragma warning(default : 1011)
368 template <
typename T,
typename U>
369 auto doConvertOptional(T
const *pv) -> std::optional<U>
371 auto eitherValueOrError = doConvert<T, U>(pv);
373 [](
auto &containedValue) -> std::optional<U> {
374 using Res = std::decay_t<decltype(containedValue)>;
375 if constexpr (std::is_same_v<Res, std::runtime_error>)
381 return {std::move(containedValue)};
389 #include "openPMD/UndefDatatypeMacros.hpp"
Definition: Attribute.hpp:64
std::variant< U, std::runtime_error > getOrError() const
Retrieve a stored specific Attribute and cast if convertible.
std::variant< Attribute, std::runtime_error > requireScalar() const
Force this attribute into a scalar type.
Definition: Attribute.cpp:230
std::variant< Attribute, std::runtime_error > requireVector() const
Force this attribute into a vector type.
Definition: Attribute.cpp:183
U get() const
Retrieve a stored specific Attribute and cast if convertible.
Definition: Attribute.cpp:112
std::optional< U > getOptional() const
Retrieve a stored specific Attribute and cast if convertible.
Definition: Attribute.cpp:132
Generic object to store a set of datatypes in without losing type safety.
Definition: Variant.hpp:40
Public definitions of openPMD-api.
Definition: Date.cpp:29
Definition: Attribute.hpp:67