1313
1414#include " Framework/RuntimeError.h"
1515#include " Framework/Array2D.h"
16+ #include " Framework/Traits.h"
1617#include < type_traits>
1718#include < cstring>
1819#include < cstdint>
@@ -261,9 +262,9 @@ struct variant_helper {
261262 new (reinterpret_cast <T*>(store)) T{};
262263 *(reinterpret_cast <T*>(store)) = value;
263264 }
264- static void set (void * store, T values, size_t size)
265+ static void set (void * store, std:: remove_pointer_t <T> const * values, size_t size)
265266 {
266- *reinterpret_cast <T*>(store) = reinterpret_cast <T>(std::memcpy (std::malloc (size * sizeof (std::remove_pointer_t <T>)), reinterpret_cast <void *>(values), size * sizeof (std::remove_pointer_t <T>)));
267+ *reinterpret_cast <T*>(store) = reinterpret_cast <T>(std::memcpy (std::malloc (size * sizeof (std::remove_pointer_t <T>)), reinterpret_cast <void const *>(values), size * sizeof (std::remove_pointer_t <T>)));
267268 }
268269
269270 static T get (const void * store) { return *(reinterpret_cast <const T*>(store)); }
@@ -317,9 +318,10 @@ struct variant_helper<std::string> {
317318class Variant
318319{
319320 public:
320- Variant (VariantType type = VariantType::Unknown) : mType {type} {}
321+ Variant (VariantType type = VariantType::Unknown);
321322
322323 template <typename T>
324+ requires (!is_specialization_v<T, std::vector>)
323325 Variant (T value) : mType {variant_trait_v<T>}
324326 {
325327 variant_helper<decltype (value)>::set (&mStore , value);
@@ -331,17 +333,22 @@ class Variant
331333 variant_helper<T>::set (&mStore , values, mSize );
332334 }
333335
336+ // A Variant owns what it stores: the content of vectors is copied
334337 template <typename T>
335- Variant (std::vector<T>& values) : mType {variant_trait_v<T*>}, mSize {values.size ()}
338+ Variant (std::vector<T> const & values) : mType {variant_trait_v<T*>}, mSize {values.size ()}
336339 {
337340 variant_helper<T*>::set (&mStore , values.data (), mSize );
338341 }
339342
340- Variant (std::vector<std::string>& values) : mType {VariantType::ArrayString}, mSize {values.size ()}
343+ Variant (std::vector<std::string> const & values) : mType {VariantType::ArrayString}, mSize {values.size ()}
341344 {
342345 variant_helper<std::vector<std::string>>::set (&mStore , values);
343346 }
344347
348+ // Prevent constructing from a temporary vector to avoid double allocation
349+ template <typename T>
350+ Variant (std::vector<T>&&) = delete ;
351+
345352 template <typename T>
346353 Variant (std::initializer_list<T>)
347354 {
@@ -355,8 +362,10 @@ class Variant
355362 ~Variant ();
356363 Variant& operator =(const Variant& other);
357364 Variant& operator =(Variant&& other) noexcept ;
365+ // Assignment from a temporary vector has to be allowed because it is used, but copies
366+ // to make sure Variant owns its content
358367 template <typename T>
359- Variant& operator =(std::vector<T>&& other) noexcept
368+ Variant& operator =(std::vector<T>&& other) // not noexcept because it allocates
360369 {
361370 *this = Variant (other);
362371 return *this ;
@@ -381,31 +390,24 @@ class Variant
381390 return variant_helper<T>::get (&mStore );
382391 }
383392
393+ // The setters replace the current content, releasing it first.
384394 template <typename T>
385395 void set (T value)
386396 {
387- return variant_helper<T>:: set (& mStore , value);
397+ * this = Variant ( value);
388398 }
389399
390400 template <typename T>
391401 void set (T value, size_t size)
392402 {
393- mSize = size;
394- return variant_helper<T>::set (&mStore , value, mSize );
395- }
396-
397- template <typename T>
398- void set (std::vector<T>& values)
399- requires(std::is_pod_v<T>)
400- {
401- return variant_helper<T*>::set (&mStore , values.data (), values.size ());
403+ *this = Variant (value, size);
402404 }
403405
404406 template <typename T>
405407 void set (std::vector<T>& values)
406- requires(std::is_same_v<T, std::string>)
408+ requires(std::is_pod_v<T> || std:: is_same_v<T, std::string>)
407409 {
408- return variant_helper<T*>:: set (& mStore , values);
410+ * this = Variant ( values);
409411 }
410412
411413 [[nodiscard]] VariantType type () const { return mType ; }
@@ -414,6 +416,10 @@ class Variant
414416
415417 private:
416418 friend std::ostream& operator <<(std::ostream& oss, Variant const & val);
419+ // Helpers to manage the store depending on the actual content
420+ void copyStore (Variant const & other);
421+ void moveStore (Variant& other) noexcept ;
422+ void destroyStore () noexcept ;
417423 using storage_t = std::aligned_union<8 , int , int8_t , int16_t , int64_t ,
418424 uint8_t , uint16_t , uint32_t , uint64_t ,
419425 const char *, float , double , bool ,
0 commit comments