@@ -60,6 +60,9 @@ class serialize_impl<
6060 // whether end() method exists
6161 decltype(std::declval<T>().end()),
6262
63+ // whether a clear() method exists
64+ decltype(std::declval<T>().clear()),
65+
6366 // whether get_size() can determine size because it has a matching overload
6467 decltype(get_size(std::declval<T>())),
6568
@@ -85,13 +88,22 @@ class serialize_impl<
8588 // Note: the following use struct templates because of a GCC bug which does
8689 // not allow static constexpr variable templates defined inside of a class.
8790
91+ // Whether it is a std::vector
92+ template <typename >
93+ struct is_vector : std::false_type
94+ {};
95+
96+ template <typename ... Ts>
97+ struct is_vector <std::vector<Ts...>> : std::true_type
98+ {};
99+
88100 // Whether it is a std::vector<bool>
89101 template <typename >
90102 struct is_vector_bool : std::false_type
91103 {};
92104
93- template <typename U >
94- struct is_vector_bool <std::vector<bool , U >> : std::true_type
105+ template <typename ... Ts >
106+ struct is_vector_bool <std::vector<bool , Ts... >> : std::true_type
95107 {};
96108
97109 // Whether it is a std::forward_list
@@ -103,16 +115,29 @@ class serialize_impl<
103115 struct is_forward_list <std::forward_list<Ts...>> : std::true_type
104116 {};
105117
106- // Whether it is a " map" (i.e. has [key, value] elements )
118+ // Whether it is a simple map (not a multimap and has integral, floating-point, enum, or convertible to string keys )
107119 template <typename , typename = void >
108- struct is_map : std::false_type
120+ struct is_simple_map : std::false_type
109121 {};
110122
111- template <template <typename ...> class U , typename ... Us>
112- struct is_map <
113- U<Us...>, std::enable_if_t <
114- is_same_template_v<U, std::map> || is_same_template_v<U, std::multimap> ||
115- is_same_template_v<U, std::unordered_map> || is_same_template_v<U, std::unordered_multimap>>> :
123+ template <template <typename ...> class MAP , typename KEY, typename ... REST>
124+ struct is_simple_map <
125+ MAP<KEY, REST...>,
126+ std::enable_if_t <(is_same_template_v<MAP, std::map> || is_same_template_v<MAP, std::unordered_map>)&&(
127+ std::is_arithmetic_v<KEY> || std::is_enum_v<KEY> || std::is_convertible_v<KEY, std::string>)>> :
128+ std::true_type
129+ {};
130+
131+ // Whether it is a simple set (not a multiset and has integral, floating-point, enum, or convertible to string keys)
132+ template <typename , typename = void >
133+ struct is_simple_set : std::false_type
134+ {};
135+
136+ template <template <typename ...> class SET , typename KEY, typename ... REST>
137+ struct is_simple_set <
138+ SET<KEY, REST...>,
139+ std::enable_if_t <(is_same_template_v<SET, std::set> || is_same_template_v<SET, std::unordered_set>)&&(
140+ std::is_arithmetic_v<KEY> || std::is_enum_v<KEY> || std::is_convertible_v<KEY, std::string>)>> :
116141 std::true_type
117142 {};
118143
@@ -145,15 +170,16 @@ class serialize_impl<
145170
146171 case serializer::UNPACK:
147172 {
148- t.~T (); // Destroy the old container
149- new (&t) T {}; // Create an empty new container
173+ size_t size;
174+ ser.unpack (size);
175+
176+ t.clear (); // Clear the container
177+ if constexpr ( is_vector<T>::value ) t.reserve (size); // Reserve size of vector
150178
151179 // For std::forward_list, last is iterator of last element inserted
152180 decltype (t.begin ()) last [[maybe_unused]];
153181 if constexpr ( is_forward_list<T>::value ) last = t.before_begin ();
154182
155- size_t size;
156- ser.unpack (size);
157183 for ( size_t i = 0 ; i < size; ++i ) {
158184 value_type e {}; // For now, elements have to be default-initializable
159185 ser& e; // Unpack the element
@@ -175,26 +201,26 @@ class serialize_impl<
175201 auto * obj_map = new ObjectMapContainer<T>(&t);
176202 ser.mapper ().map_hierarchy_start (name, obj_map);
177203
178- if constexpr ( is_map<T>::value ) {
179- // (key, value) mappings
180- // TODO: how to handle std::multimap and std::unordered_multimap with equal keys
181- // auto [ begin, end ] = equal_range(key) returns range of elements equal to key
204+ if constexpr ( is_vector_bool<T>::value ) {
205+ // std::vector<bool>
206+ size_t i = 0 ;
207+ for ( bool e : t )
208+ sst_map_object (ser, e, to_string (i++));
209+ }
210+ else if constexpr ( is_simple_map<T>::value ) {
211+ // non-multi maps with a simple key
182212 for ( auto & [key, value] : t )
183213 sst_map_object (ser, value, to_string (key));
184214 }
185- else if constexpr ( !is_vector_bool<T>::value ) {
186- // std::vector, std::deque, std::list, std::forward_list, std::set, std::multiset
187- // std::unordered_set, std::unordered_multiset
215+ // TODO: handle is_simple_set
216+ else {
217+ // std::vector, std::deque, std::list, std::forward_list, std::multimap,
218+ // std::unordered_multimap, std::multiset, std::unordered_multiset, and
219+ // std::map, std::set, std::unordered_map std::unordered_set with non-simple keys
188220 size_t i = 0 ;
189221 for ( auto & e : t )
190222 sst_map_object (ser, (value_type&)e, to_string (i++));
191223 }
192- else {
193- // std::vector<bool>
194- size_t i = 0 ;
195- for ( bool e : t )
196- sst_map_object (ser, e, to_string (i++));
197- }
198224 ser.mapper ().map_hierarchy_end ();
199225 break ;
200226 }
0 commit comments