1 #ifndef SERIALIZE_META_HH
2 #define SERIALIZE_META_HH
10 #include <type_traits>
32 template<
typename TUPLE>
34 auto makeT = [](
auto&& ...args) {
35 return std::make_unique<T>(std::forward<decltype(args)>(args)...);
37 return std::apply(makeT, tuple);
48 template<
typename T>
struct ClassSaver;
51 template<
typename T>
struct NonPolymorphicPointerLoader;
53 template<
typename T>
struct ClassLoader;
72 return std::tuple<>();
79 static_assert(std::is_same_v<TUPLEIn, TUPLEOut>,
80 "constructor argument types must match");
100 : std::conditional_t<std::is_same<std::tuple<>,
101 typename PolymorphicConstructorArgs<Derived>::type>::value,
102 MapConstrArgsEmpty<Base>,
103 MapConstrArgsCopy<Base, Derived>> {};
113 void polyInitError(
const char* expected,
const char* actual);
115 template<
typename Archive>
126 static_assert(std::is_polymorphic_v<T>,
127 "must be a polymorphic type");
128 static_assert(!std::is_abstract_v<T>,
129 "can't be an abstract type");
130 registerHelper(
typeid(T), [name](Archive& ar,
const void* v) {
132 auto base =
static_cast<const BaseType*
>(v);
133 auto tp =
static_cast<const T*
>(base);
135 saver(ar, *tp,
true, name,
true);
139 template<
typename T>
static void save(Archive& ar, T*
t)
143 template<
typename T>
static void save(
const char* tag, Archive& ar, T&
t)
145 save(tag, ar, &
t,
typeid(
t));
152 using SaveFunction = std::function<void(Archive&,
const void*)>;
153 void registerHelper(
const std::type_info& type,
155 static void save(Archive& ar,
const void*
t,
156 const std::type_info& typeInfo);
157 static void save(
const char* tag, Archive& ar,
const void*
t,
158 const std::type_info& typeInfo);
161 std::type_index index;
164 std::vector<Entry> saverMap;
165 bool initialized =
false;
168 template<
typename Archive>
179 static_assert(std::is_polymorphic_v<T>,
180 "must be a polymorphic type");
181 static_assert(!std::is_abstract_v<T>,
182 "can't be an abstract type");
183 registerHelper(name, [](Archive& ar,
unsigned id,
const void* args) {
187 auto& argsIn = *
static_cast<const TUPLEIn*
>(args);
189 TUPLEOut argsOut = mapArgs(argsIn);
191 return loader(ar,
id, argsOut);
195 static void*
load(Archive& ar,
unsigned id,
const void* args);
201 using LoadFunction = std::function<
void*(Archive&, unsigned,
const void*)>;
202 void registerHelper(
const char* name, LoadFunction loader);
207 template<
typename Archive>
218 static_assert(std::is_polymorphic_v<T>,
219 "must be a polymorphic type");
220 static_assert(!std::is_abstract_v<T>,
221 "can't be an abstract type");
222 registerHelper(name, [](Archive& ar,
void* v,
unsigned id) {
224 auto base =
static_cast<BaseType*
>(v);
225 if (
unlikely(
dynamic_cast<T*
>(base) !=
static_cast<T*
>(base))) {
228 auto t =
static_cast<T*
>(base);
230 loader(ar, *
t, std::tuple<>(),
id);
234 static void init(
const char* tag, Archive& ar,
void*
t);
240 using InitFunction = std::function<void(Archive&,
void*,
unsigned)>;
241 void registerHelper(
const char* name, InitFunction initializer);
252 template registerClass<T>(name);
260 template registerClass<T>(name);
268 template registerClass<T>(name);
272 #define REGISTER_CONSTRUCTOR_ARGS_0(C) \
273 template<> struct PolymorphicConstructorArgs<C> \
274 { using type = std::tuple<>; };
276 #define REGISTER_CONSTRUCTOR_ARGS_1(C,T1) \
277 template<> struct PolymorphicConstructorArgs<C> \
278 { using type = std::tuple<T1>; };
280 #define REGISTER_CONSTRUCTOR_ARGS_2(C,T1,T2) \
281 template<> struct PolymorphicConstructorArgs<C> \
282 { using type = std::tuple<T1,T2>; };
284 #define REGISTER_CONSTRUCTOR_ARGS_3(C,T1,T2,T3) \
285 template<> struct PolymorphicConstructorArgs<C> \
286 { using type = std::tuple<T1,T2,T3>; };
288 class MemInputArchive;
289 class MemOutputArchive;
290 class XmlInputArchive;
291 class XmlOutputArchive;
301 #define REGISTER_POLYMORPHIC_CLASS_HELPER(B,C,N) \
302 static_assert(std::is_base_of_v<B,C>, "must be base and sub class"); \
303 static RegisterLoaderHelper<MemInputArchive, C> registerHelper3##C(N); \
304 static RegisterSaverHelper <MemOutputArchive, C> registerHelper4##C(N); \
305 static RegisterLoaderHelper<XmlInputArchive, C> registerHelper5##C(N); \
306 static RegisterSaverHelper <XmlOutputArchive, C> registerHelper6##C(N); \
307 template<> struct PolymorphicBaseClass<C> { using type = B; };
309 #define REGISTER_POLYMORPHIC_INITIALIZER_HELPER(B,C,N) \
310 static_assert(std::is_base_of_v<B,C>, "must be base and sub class"); \
311 static RegisterInitializerHelper<MemInputArchive, C> registerHelper3##C(N); \
312 static RegisterSaverHelper <MemOutputArchive, C> registerHelper4##C(N); \
313 static RegisterInitializerHelper<XmlInputArchive, C> registerHelper5##C(N); \
314 static RegisterSaverHelper <XmlOutputArchive, C> registerHelper6##C(N); \
315 template<> struct PolymorphicBaseClass<C> { using type = B; };
317 #define REGISTER_BASE_NAME_HELPER(B,N) \
318 template<> struct BaseClassName<B> \
319 { static const char* getName() { static constexpr const char* const name = N; return name; } };
324 #define REGISTER_POLYMORPHIC_CLASS(BASE,CLASS,NAME) \
325 REGISTER_POLYMORPHIC_CLASS_HELPER(BASE,CLASS,NAME) \
326 REGISTER_CONSTRUCTOR_ARGS_0(CLASS)
328 #define REGISTER_POLYMORPHIC_CLASS_1(BASE,CLASS,NAME,TYPE1) \
329 REGISTER_POLYMORPHIC_CLASS_HELPER(BASE,CLASS,NAME) \
330 REGISTER_CONSTRUCTOR_ARGS_1(CLASS,TYPE1)
332 #define REGISTER_POLYMORPHIC_CLASS_2(BASE,CLASS,NAME,TYPE1,TYPE2) \
333 REGISTER_POLYMORPHIC_CLASS_HELPER(BASE,CLASS,NAME) \
334 REGISTER_CONSTRUCTOR_ARGS_2(CLASS,TYPE1,TYPE2)
336 #define REGISTER_POLYMORPHIC_CLASS_3(BASE,CLASS,NAME,TYPE1,TYPE2,TYPE3) \
337 REGISTER_POLYMORPHIC_CLASS_HELPER(BASE,CLASS,NAME) \
338 REGISTER_CONSTRUCTOR_ARGS_3(CLASS,TYPE1,TYPE2,TYPE3)
340 #define REGISTER_BASE_CLASS(CLASS,NAME) \
341 REGISTER_BASE_NAME_HELPER(CLASS,NAME) \
342 REGISTER_CONSTRUCTOR_ARGS_0(CLASS)
344 #define REGISTER_BASE_CLASS_1(CLASS,NAME,TYPE1) \
345 REGISTER_BASE_NAME_HELPER(CLASS,NAME) \
346 REGISTER_CONSTRUCTOR_ARGS_1(CLASS,TYPE1)
348 #define REGISTER_BASE_CLASS_2(CLASS,NAME,TYPE1,TYPE2) \
349 REGISTER_BASE_NAME_HELPER(CLASS,NAME) \
350 REGISTER_CONSTRUCTOR_ARGS_2(CLASS,TYPE1,TYPE2)
352 #define REGISTER_BASE_CLASS_3(CLASS,NAME,TYPE1,TYPE2,TYPE3) \
353 REGISTER_BASE_NAME_HELPER(CLASS,NAME) \
354 REGISTER_CONSTRUCTOR_ARGS_3(CLASS,TYPE1,TYPE2,TYPE3)
357 #define REGISTER_POLYMORPHIC_INITIALIZER(BASE,CLASS,NAME) \
358 REGISTER_POLYMORPHIC_INITIALIZER_HELPER(BASE,CLASS,NAME)
379 static constexpr
unsigned value = 1;
381 #define SERIALIZE_CLASS_VERSION(CLASS, VERSION) \
382 template<> struct SerializeClassVersion<CLASS> \
384 static constexpr unsigned value = VERSION; \
static void init(const char *tag, Archive &ar, void *t)
PolymorphicInitializerRegistry(const PolymorphicInitializerRegistry &)=delete
PolymorphicInitializerRegistry & operator=(const PolymorphicInitializerRegistry &)=delete
static PolymorphicInitializerRegistry & instance()
void registerClass(const char *name)
static PolymorphicLoaderRegistry & instance()
void registerClass(const char *name)
static void * load(Archive &ar, unsigned id, const void *args)
PolymorphicLoaderRegistry(const PolymorphicLoaderRegistry &)=delete
PolymorphicLoaderRegistry & operator=(const PolymorphicLoaderRegistry &)=delete
PolymorphicSaverRegistry(const PolymorphicSaverRegistry &)=delete
static PolymorphicSaverRegistry & instance()
PolymorphicSaverRegistry & operator=(const PolymorphicSaverRegistry &)=delete
static void save(const char *tag, Archive &ar, T &t)
void registerClass(const char *name)
static void save(Archive &ar, T *t)
This file implemented 3 utility functions:
void polyInitError(const char *expected, const char *actual)
Stores the name of a base class.
Utility to do T* t = new T(...)
std::unique_ptr< T > operator()(TUPLE tuple)
typename PolymorphicConstructorArgs< Base >::type TUPLEIn
TUPLEOut operator()(const TUPLEIn &t)
typename PolymorphicConstructorArgs< Derived >::type TUPLEOut
std::tuple operator()(const TUPLEIn &)
typename PolymorphicConstructorArgs< Base >::type TUPLEIn
Define mapping between constructor arg list of base- and subclass.
Store association between (polymorphic) sub- and baseclass.
Store association between polymorphic class (base- or subclass) and the list of constructor arguments...
RegisterInitializerHelper(const char *name)
RegisterLoaderHelper(const char *name)
RegisterSaverHelper(const char *name)
Store serialization-version number of a class.