From 616c7b4e968a8ffa5ef9aa340810ce01b1392a63 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:19:36 +0200 Subject: [PATCH] Fix variant for std::vector string --- Framework/Core/include/Framework/Variant.h | 98 ++++++++++++++-------- Framework/Core/src/Variant.cxx | 36 ++++---- 2 files changed, 79 insertions(+), 55 deletions(-) diff --git a/Framework/Core/include/Framework/Variant.h b/Framework/Core/include/Framework/Variant.h index 54e4b54be9606..54a91e90c3638 100644 --- a/Framework/Core/include/Framework/Variant.h +++ b/Framework/Core/include/Framework/Variant.h @@ -254,75 +254,85 @@ DECLARE_VARIANT_ARRAY_ELEMENT_TYPE(std::string, LabeledArrayString); template using variant_array_element_type_t = typename variant_array_element_type::type; -template +template struct variant_helper { - static void set(S* store, T value) + static void set(void* store, T value) { new (reinterpret_cast(store)) T{}; *(reinterpret_cast(store)) = value; } - static void set(S* store, T values, size_t size) + static void set(void* store, T values, size_t size) { *reinterpret_cast(store) = reinterpret_cast(std::memcpy(std::malloc(size * sizeof(std::remove_pointer_t)), reinterpret_cast(values), size * sizeof(std::remove_pointer_t))); } - static T get(const S* store) { return *(reinterpret_cast(store)); } + static T get(const void* store) { return *(reinterpret_cast(store)); } +}; + +template <> +struct variant_helper> { + // Allocates a new store and copies into it. + static void set(void* store, std::vector value) + { + new (reinterpret_cast*>(store)) std::vector{}; + *(reinterpret_cast*>(store)) = value; + } + + static std::vector const& get(const void* store) { return *(reinterpret_cast const*>(store)); } }; -template -struct variant_helper { - static const char* get(const S* store) { return *reinterpret_cast(store); } +template <> +struct variant_helper { + static const char* get(const void* store) { return *reinterpret_cast(store); } - static void set(S* store, const char* value) { *reinterpret_cast(store) = strdup(value); } + static void set(void* store, const char* value) { *reinterpret_cast(store) = strdup(value); } }; -template -struct variant_helper { - static std::string_view get(const S* store) { return std::string_view(*reinterpret_cast(store)); } +template <> +struct variant_helper { + static std::string_view get(const void* store) { return std::string_view(*reinterpret_cast(store)); } - static void set(S* store, std::string_view value) { *reinterpret_cast(store) = strdup(value.data()); } + static void set(void* store, std::string_view value) { *reinterpret_cast(store) = strdup(value.data()); } }; -template -struct variant_helper { - static std::string get(const S* store) { return std::string(*reinterpret_cast(store)); } +template <> +struct variant_helper { + static std::string get(const void* store) { return std::string(*reinterpret_cast(store)); } - static void set(S* store, std::string value) { *reinterpret_cast(store) = strdup(value.data()); } + static void set(void* store, std::string value) { *reinterpret_cast(store) = strdup(value.data()); } }; /// Variant for configuration parameter storage. Owns stored data. class Variant { - using storage_t = std::aligned_union<8, int, int8_t, int16_t, int64_t, - uint8_t, uint16_t, uint32_t, uint64_t, - const char*, float, double, bool, - int*, float*, double*, bool*, std::string*, - Array2D, Array2D, Array2D, Array2D, - LabeledArray, LabeledArray, LabeledArray, LabeledArray>::type; - public: - Variant(VariantType type = VariantType::Unknown) : mType{type}, mSize{1} {} + Variant(VariantType type = VariantType::Unknown) : mType{type} {} template - Variant(T value) : mType{variant_trait_v}, mSize{1} + Variant(T value) : mType{variant_trait_v} { - variant_helper::set(&mStore, value); + variant_helper::set(&mStore, value); } template Variant(T values, size_t size) : mType{variant_trait_v}, mSize{size} { - variant_helper::set(&mStore, values, mSize); + variant_helper::set(&mStore, values, mSize); } template Variant(std::vector& values) : mType{variant_trait_v}, mSize{values.size()} { - variant_helper::set(&mStore, values.data(), mSize); + variant_helper::set(&mStore, values.data(), mSize); + } + + Variant(std::vector& values) : mType{VariantType::ArrayString}, mSize{values.size()} + { + variant_helper>::set(&mStore, values); } template - Variant(std::initializer_list) : mType{VariantType::Unknown}, mSize{1} + Variant(std::initializer_list) { static_assert(sizeof(T) == 0, "brace-enclosed initializer list forbidden for Variant" @@ -347,36 +357,50 @@ class Variant if (mType != variant_trait_v) { throw runtime_error("Mismatch between types"); } - return variant_helper::get(&mStore); + return variant_helper::get(&mStore); } template void set(T value) { - return variant_helper::set(&mStore, value); + return variant_helper::set(&mStore, value); } template void set(T value, size_t size) { mSize = size; - return variant_helper::set(&mStore, value, mSize); + return variant_helper::set(&mStore, value, mSize); } template void set(std::vector& values) + requires(std::is_pod_v) { - return variant_helper::set(&mStore, values.data(), values.size()); + return variant_helper::set(&mStore, values.data(), values.size()); } - VariantType type() const { return mType; } - size_t size() const { return mSize; } - std::string asString() const; + template + void set(std::vector& values) + requires(std::is_same_v) + { + return variant_helper::set(&mStore, values); + } + + [[nodiscard]] VariantType type() const { return mType; } + [[nodiscard]] size_t size() const { return mSize; } + [[nodiscard]] std::string asString() const; private: friend std::ostream& operator<<(std::ostream& oss, Variant const& val); + using storage_t = std::aligned_union<8, int, int8_t, int16_t, int64_t, + uint8_t, uint16_t, uint32_t, uint64_t, + const char*, float, double, bool, + int*, float*, double*, bool*, std::string*, + Array2D, Array2D, Array2D, Array2D, + LabeledArray, LabeledArray, LabeledArray, LabeledArray>::type; storage_t mStore; - VariantType mType; + VariantType mType = VariantType::Unknown; size_t mSize = 1; }; diff --git a/Framework/Core/src/Variant.cxx b/Framework/Core/src/Variant.cxx index 3f71ec339511e..21eb6103aa56a 100644 --- a/Framework/Core/src/Variant.cxx +++ b/Framework/Core/src/Variant.cxx @@ -91,27 +91,27 @@ Variant::Variant(const Variant& other) : mType(other.mType) switch (mType) { case variant_trait_v: mSize = other.mSize; - variant_helper::set(&mStore, other.get()); + variant_helper::set(&mStore, other.get()); return; case variant_trait_v: mSize = other.mSize; - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return; case variant_trait_v: mSize = other.mSize; - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return; case variant_trait_v: mSize = other.mSize; - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return; case variant_trait_v: mSize = other.mSize; - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return; case variant_trait_v: mSize = other.mSize; - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return; default: mStore = other.mStore; @@ -172,22 +172,22 @@ Variant& Variant::operator=(const Variant& other) mType = other.mType; switch (mType) { case variant_trait_v: - variant_helper::set(&mStore, other.get()); + variant_helper::set(&mStore, other.get()); return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); return *this; default: mStore = other.mStore; @@ -201,27 +201,27 @@ Variant& Variant::operator=(Variant&& other) noexcept mType = other.mType; switch (mType) { case variant_trait_v: - variant_helper::set(&mStore, other.get()); + variant_helper::set(&mStore, other.get()); *reinterpret_cast(&(other.mStore)) = nullptr; return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); *reinterpret_cast(&(other.mStore)) = nullptr; return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); *reinterpret_cast(&(other.mStore)) = nullptr; return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); *reinterpret_cast(&(other.mStore)) = nullptr; return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); *reinterpret_cast(&(other.mStore)) = nullptr; return *this; case variant_trait_v: - variant_helper::set(&mStore, other.get(), mSize); + variant_helper::set(&mStore, other.get(), mSize); *reinterpret_cast(&(other.mStore)) = nullptr; return *this; default: