diff --git a/include/openPMD/DatatypeMacros.hpp b/include/openPMD/DatatypeMacros.hpp
new file mode 100644
index 0000000000..aa78879aab
--- /dev/null
+++ b/include/openPMD/DatatypeMacros.hpp
@@ -0,0 +1,113 @@
+/* Copyright 2023 Franz Poeschel
+ *
+ * This file is part of openPMD-api.
+ *
+ * openPMD-api is free software: you can redistribute it and/or modify
+ * it under the terms of of either the GNU General Public License or
+ * the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * openPMD-api is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with openPMD-api.
+ * If not, see .
+ */
+#pragma once
+
+#include
+#include
+#include
+
+// Need to alias this to avoid the comma
+// Cannot use a namespace, otherwise the macro will work either only within
+// or outside the namespace
+// Defining macros means polluting the global namespace anyway
+using openpmd_array_double_7 = std::array;
+
+#define OPENPMD_FOREACH_DATATYPE(MACRO) \
+ MACRO(char) \
+ MACRO(unsigned char) \
+ MACRO(signed char) \
+ MACRO(short) \
+ MACRO(int) \
+ MACRO(long) \
+ MACRO(long long) \
+ MACRO(unsigned short) \
+ MACRO(unsigned int) \
+ MACRO(unsigned long) \
+ MACRO(unsigned long long) \
+ MACRO(float) \
+ MACRO(double) \
+ MACRO(long double) \
+ MACRO(std::complex) \
+ MACRO(std::complex) \
+ MACRO(std::complex) \
+ MACRO(std::string) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(std::vector>) \
+ MACRO(std::vector>) \
+ MACRO(std::vector>) \
+ MACRO(std::vector) \
+ MACRO(std::vector) \
+ MACRO(openpmd_array_double_7) \
+ MACRO(bool)
+
+#define OPENPMD_FOREACH_NONVECTOR_DATATYPE(MACRO) \
+ MACRO(char) \
+ MACRO(unsigned char) \
+ MACRO(signed char) \
+ MACRO(short) \
+ MACRO(int) \
+ MACRO(long) \
+ MACRO(long long) \
+ MACRO(unsigned short) \
+ MACRO(unsigned int) \
+ MACRO(unsigned long) \
+ MACRO(unsigned long long) \
+ MACRO(float) \
+ MACRO(double) \
+ MACRO(long double) \
+ MACRO(std::complex) \
+ MACRO(std::complex) \
+ MACRO(std::complex) \
+ MACRO(std::string) \
+ MACRO(array_double_7) \
+ MACRO(bool)
+
+#define OPENPMD_FOREACH_DATASET_DATATYPE(MACRO) \
+ MACRO(char) \
+ MACRO(unsigned char) \
+ MACRO(signed char) \
+ MACRO(short) \
+ MACRO(int) \
+ MACRO(long) \
+ MACRO(long long) \
+ MACRO(unsigned short) \
+ MACRO(unsigned int) \
+ MACRO(unsigned long) \
+ MACRO(unsigned long long) \
+ MACRO(float) \
+ MACRO(double) \
+ MACRO(long double) \
+ MACRO(std::complex) \
+ MACRO(std::complex) \
+ MACRO(std::complex) \
+ MACRO(std::array)
diff --git a/include/openPMD/UndefDatatypeMacros.hpp b/include/openPMD/UndefDatatypeMacros.hpp
new file mode 100644
index 0000000000..f55303ca11
--- /dev/null
+++ b/include/openPMD/UndefDatatypeMacros.hpp
@@ -0,0 +1,24 @@
+/* Copyright 2023 Franz Poeschel
+ *
+ * This file is part of openPMD-api.
+ *
+ * openPMD-api is free software: you can redistribute it and/or modify
+ * it under the terms of of either the GNU General Public License or
+ * the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * openPMD-api is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with openPMD-api.
+ * If not, see .
+ */
+
+#undef OPENPMD_FOREACH_DATATYPE
+#undef OPENPMD_FOREACH_NONVECTOR_DATATYPE
+#undef OPENPMD_FOREACH_DATASET_DATATYPE
diff --git a/include/openPMD/backend/Attribute.hpp b/include/openPMD/backend/Attribute.hpp
index ecc445fff5..c34d7c1847 100644
--- a/include/openPMD/backend/Attribute.hpp
+++ b/include/openPMD/backend/Attribute.hpp
@@ -21,6 +21,7 @@
#pragma once
#include "openPMD/Datatype.hpp"
+#include "openPMD/DatatypeMacros.hpp"
#include "openPMD/auxiliary/TypeTraits.hpp"
#include "openPMD/auxiliary/Variant.hpp"
@@ -106,17 +107,15 @@ class Attribute
*
* Fix by explicitly instantiating resource
*/
- template
- Attribute(std::enable_if_t<
- // If T is `Attribute` or `Attribute const &`, this constructor
- // should not be used, but instead the move/copy constructors
- !std::is_same_v<
- std::remove_cv_t>,
- Attribute>,
- T> &&val)
- : Variant(resource(std::forward(val)))
+
+#define OPENPMD_ATTRIBUTE_CONSTRUCTOR_FROM_VARIANT(TYPE) \
+ Attribute(TYPE val) : Variant(resource(std::move(val))) \
{}
+ OPENPMD_FOREACH_DATATYPE(OPENPMD_ATTRIBUTE_CONSTRUCTOR_FROM_VARIANT)
+
+#undef OPENPMD_ATTRIBUTE_CONSTRUCTOR_FROM_VARIANT
+
/** Retrieve a stored specific Attribute and cast if convertible.
*
* @note This performs a static_cast and might introduce precision loss if
@@ -304,3 +303,5 @@ std::optional Attribute::getOptional() const
std::move(eitherValueOrError));
}
} // namespace openPMD
+
+#include "openPMD/UndefDatatypeMacros.hpp"