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>
119 template <
typename U>
120 std::variant<U, std::runtime_error> get_impl()
const;
125 template <
typename T,
typename U>
126 auto doConvert(T
const *pv) -> std::variant<U, std::runtime_error>
129 if constexpr (std::is_convertible_v<T, U>)
131 return {
static_cast<U
>(*pv)};
134 std::is_same_v<T, std::string> && auxiliary::IsChar_v<U>)
138 return static_cast<U
>(pv->at(0));
142 return {std::runtime_error(
143 "getCast: cast from string to char only "
144 "possible if string has length 1.")};
148 auxiliary::IsChar_v<T> && std::is_same_v<U, std::string>)
150 return std::string(1, *pv);
152 else if constexpr (auxiliary::IsVector_v<T> && auxiliary::IsVector_v<U>)
155 res.reserve(pv->size());
156 if constexpr (std::is_convertible_v<
157 typename T::value_type,
158 typename U::value_type>)
160 std::copy(pv->begin(), pv->end(), std::back_inserter(res));
166 for (
auto const &val : *pv)
168 auto conv = doConvert<
169 typename T::value_type,
170 typename U::value_type>(&val);
172 std::get_if<typename U::value_type>(&conv);
175 res.push_back(std::move(*conv_val));
179 auto exception = std::get<std::runtime_error>(conv);
180 return {std::runtime_error(
182 "getCast: no vector cast possible, recursive "
193 else if constexpr (auxiliary::IsArray_v<T> && auxiliary::IsVector_v<U>)
196 res.reserve(pv->size());
197 if constexpr (std::is_convertible_v<
198 typename T::value_type,
199 typename U::value_type>)
201 std::copy(pv->begin(), pv->end(), std::back_inserter(res));
207 for (
auto const &val : *pv)
209 auto conv = doConvert<
210 typename T::value_type,
211 typename U::value_type>(&val);
213 std::get_if<typename U::value_type>(&conv);
216 res.push_back(std::move(*conv_val));
220 auto exception = std::get<std::runtime_error>(conv);
221 return {std::runtime_error(
223 "getCast: no array to vector conversion "
224 "possible, recursive error: ") +
234 else if constexpr (auxiliary::IsVector_v<T> && auxiliary::IsArray_v<U>)
237 if constexpr (std::is_convertible_v<
238 typename T::value_type,
239 typename U::value_type>)
241 if (res.size() != pv->size())
243 return std::runtime_error(
244 "getCast: no vector to array conversion possible "
246 "requested array size).");
248 for (
size_t i = 0; i < res.size(); ++i)
250 res[i] =
static_cast<typename U::value_type
>((*pv)[i]);
257 for (
size_t i = 0; i <= res.size(); ++i)
259 auto const &val = (*pv)[i];
260 auto conv = doConvert<
261 typename T::value_type,
262 typename U::value_type>(&val);
264 std::get_if<typename U::value_type>(&conv);
267 res[i] = std::move(*conv_val);
271 auto exception = std::get<std::runtime_error>(conv);
272 return {std::runtime_error(
274 "getCast: no vector to array conversion "
275 "possible, recursive error: ") +
283 else if constexpr (auxiliary::IsVector_v<U>)
287 if constexpr (std::is_convertible_v<T, typename U::value_type>)
289 res.push_back(
static_cast<typename U::value_type
>(*pv));
295 auto conv = doConvert<T, typename U::value_type>(pv);
296 if (
auto conv_val = std::get_if<typename U::value_type>(&conv);
299 res.push_back(std::move(*conv_val));
304 auto exception = std::get<std::runtime_error>(conv);
305 return {std::runtime_error(
307 "getCast: no scalar to vector conversion "
308 "possible, recursive error: ") +
315 return {std::runtime_error(
"getCast: no cast possible.")};
317 #if defined(__INTEL_COMPILER)
325 #pragma warning(disable : 1011)
327 #pragma warning(default : 1011)
332 template <
typename T,
typename U>
333 auto doConvertOptional(T
const *pv) -> std::optional<U>
335 auto eitherValueOrError = doConvert<T, U>(pv);
337 [](
auto &containedValue) -> std::optional<U> {
338 using Res = std::decay_t<decltype(containedValue)>;
339 if constexpr (std::is_same_v<Res, std::runtime_error>)
345 return {std::move(containedValue)};
353 #include "openPMD/UndefDatatypeMacros.hpp"
Definition: Attribute.hpp:64
U get() const
Retrieve a stored specific Attribute and cast if convertible.
Definition: Attribute.cpp:105
std::optional< U > getOptional() const
Retrieve a stored specific Attribute and cast if convertible.
Definition: Attribute.cpp:125
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