SST 16.0.0
Structural Simulation Toolkit
serialize_aggregate.h
1// Copyright 2009-2026 NTESS. Under the terms
2// of Contract DE-NA0003525 with NTESS, the U.S.
3// Government retains certain rights in this software.
4//
5// Copyright (c) 2009-2026, NTESS
6// All rights reserved.
7//
8// This file is part of the SST software package. For license
9// information, see the LICENSE file in the top level directory of the
10// distribution.
11
12#ifndef SST_CORE_SERIALIZATION_IMPL_SERIALIZE_AGGREGATE_H
13#define SST_CORE_SERIALIZATION_IMPL_SERIALIZE_AGGREGATE_H
14
15#ifndef SST_INCLUDING_SERIALIZE_H
16#warning \
17 "The header file sst/core/serialization/impl/serialize_aggregate.h should not be directly included as it is not part of the stable public API. The file is included in sst/core/serialization/serialize.h"
18#endif
19
20#include "sst/core/serialization/impl/serialize_utility.h"
21#include "sst/core/serialization/serializer.h"
22
23#include <array>
24#include <cstddef>
25#include <string>
26#include <tuple>
27#include <type_traits>
28#include <utility>
29
30namespace SST::Core::Serialization {
31
32/////////////////////////////////////////////////////////////////////////////////////////////////////
33// Aggregate serialization //
34// //
35// An aggregate is a C-style array, std::array, or a class/struct/union with all public non-static //
36// data members and direct bases, no user-provided, inherited or explicit constructors (C++17), no //
37// user-declared or inherited constructors (C++20), and no virtual functions or virtual bases. //
38// //
39// For aggregates which are either not trivially copyable or are not standard layout types, they //
40// can be serialized by using structured bindings to extract their members and serialize each //
41// member separately. The serialization implementation needs to be specialized for each member //
42// count, because until C++26, structured binding packs are not supported. //
43// //
44// For aggregate serialization, //
45// - It must be an aggregate class type //
46// - It must not be trivially serializable //
47// - It must not have a serialize_order() method //
48// - It must not contain anonymous union members (not detectable in C++17 except by error) //
49// - The number of fields must be supported by the implementation below //
50/////////////////////////////////////////////////////////////////////////////////////////////////////
51
52namespace pvt {
53
54template <typename>
56
57// For a sequence of indices, serialize each element of an aggregate
58// This is only used in mapping mode
59template <size_t... INDEX>
60struct serialize_aggregate_map_impl<std::index_sequence<INDEX...>>
61{
62 template <typename T>
63 void operator()(T&& t, serializer& ser, ser_opt_t opt)
64 {
65 // Serialize each element
66 (SST_SER_NAME(std::get<INDEX>(t), std::to_string(INDEX).c_str(), opt), ...);
67 }
68};
69
70template <typename T, size_t NFIELDS>
71struct serialize_aggregate_impl : std::false_type
72{};
73
74// Structured binding extracts NFIELDS fields in __VA_ARGS__ and serializes each one separately
75#define SERIALIZE_AGGREGATE_IMPL(NFIELDS, ...) \
76 template <typename T> \
77 struct serialize_aggregate_impl<T, NFIELDS> : std::true_type \
78 { \
79 void operator()(T& t, serializer& ser, ser_opt_t opt) \
80 { \
81 auto& [__VA_ARGS__] = t; \
82 if ( ser.mode() == serializer::MAP ) { \
83 ser.mapper().map_hierarchy_start(ser.getMapName(), new ObjectMapContainer<T>(&t)); \
84 serialize_aggregate_map_impl<std::make_index_sequence<NFIELDS>>()(std::tie(__VA_ARGS__), ser, opt); \
85 ser.mapper().map_hierarchy_end(); \
86 } \
87 else { \
88 [&](auto&... e) { (SST_SER(e), ...); }(__VA_ARGS__); \
89 } \
90 } \
91 }
92
93SERIALIZE_AGGREGATE_IMPL(1, a0);
94SERIALIZE_AGGREGATE_IMPL(2, a0, a1);
95SERIALIZE_AGGREGATE_IMPL(3, a0, a1, a2);
96SERIALIZE_AGGREGATE_IMPL(4, a0, a1, a2, a3);
97SERIALIZE_AGGREGATE_IMPL(5, a0, a1, a2, a3, a4);
98SERIALIZE_AGGREGATE_IMPL(6, a0, a1, a2, a3, a4, a5);
99SERIALIZE_AGGREGATE_IMPL(7, a0, a1, a2, a3, a4, a5, a6);
100SERIALIZE_AGGREGATE_IMPL(8, a0, a1, a2, a3, a4, a5, a6, a7);
101SERIALIZE_AGGREGATE_IMPL(9, a0, a1, a2, a3, a4, a5, a6, a7, a8);
102SERIALIZE_AGGREGATE_IMPL(10, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
103SERIALIZE_AGGREGATE_IMPL(11, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
104SERIALIZE_AGGREGATE_IMPL(12, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
105SERIALIZE_AGGREGATE_IMPL(13, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
106SERIALIZE_AGGREGATE_IMPL(14, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13);
107SERIALIZE_AGGREGATE_IMPL(15, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
108SERIALIZE_AGGREGATE_IMPL(16, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15);
109SERIALIZE_AGGREGATE_IMPL(17, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16);
110SERIALIZE_AGGREGATE_IMPL(18, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17);
111SERIALIZE_AGGREGATE_IMPL(19, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18);
112SERIALIZE_AGGREGATE_IMPL(20, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19);
113
114// An aggregate class type with no serialize_order() method, an implementation of serialize_aggregate_impl for the
115// number of fields, and not trivially serializable
116template <typename T>
117constexpr bool is_aggregate_serializable_v =
118 std::conjunction_v<std::is_class<T>, std::is_aggregate<T>, std::negation<has_serialize_order<T>>,
119 serialize_aggregate_impl<T, nfields<T>>, std::negation<is_trivially_serializable<T>>>;
120
121// std::array is excluded because it is handled in serialize_array.h
122template <typename T, size_t N>
123constexpr bool is_aggregate_serializable_v<std::array<T, N>> = false;
124
125} // namespace pvt
126
127// Serialize aggregate class types which are not trivially serializable
128template <typename T>
129class serialize_impl<T, std::enable_if_t<pvt::is_aggregate_serializable_v<T>>> :
130 pvt::serialize_aggregate_impl<T, nfields<T>>
131{
132 SST_FRIEND_SERIALIZE();
133};
134
135} // namespace SST::Core::Serialization
136
137#endif // SST_CORE_SERIALIZATION_IMPL_SERIALIZE_AGGREGATE_H
Base serialize class.
Definition serialize.h:132
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition serializer.h:43