diff options
author | Johannes Schanda <schanda@itestra.de> | 2013-05-29 23:13:34 +0200 |
---|---|---|
committer | Johannes Schanda <schanda@itestra.de> | 2013-05-29 23:13:34 +0200 |
commit | be635b51f6ad0b978a3aa8f7e1a167495b9f3b70 (patch) | |
tree | bbe1f0c4642942080e41a12209a3a50855c7b4b1 /src | |
parent | 447790b568b7d2710ae10ddeb16d57b19561757e (diff) | |
download | genivi-common-api-runtime-be635b51f6ad0b978a3aa8f7e1a167495b9f3b70.tar.gz |
Corrected move constructor / initialisation of empty variant
Diffstat (limited to 'src')
-rw-r--r-- | src/CommonAPI/SerializableVariant.h | 15 | ||||
-rw-r--r-- | src/CommonAPI/SerializableVariant.hpp | 80 | ||||
-rwxr-xr-x | src/test/VariantTest.cpp | 59 |
3 files changed, 119 insertions, 35 deletions
diff --git a/src/CommonAPI/SerializableVariant.h b/src/CommonAPI/SerializableVariant.h index 51f8224..37f7320 100644 --- a/src/CommonAPI/SerializableVariant.h +++ b/src/CommonAPI/SerializableVariant.h @@ -198,13 +198,18 @@ public: typename std::enable_if<!std::is_reference<_Type>::value>::type* = 0, typename std::enable_if<!std::is_same<_Type, Variant>::value>::type* = 0); + /** + * \brief Get value of variant, template to content type. Throws exception if type is not contained. + * + * Get value of variant, template to content type. Throws exception if type is not contained. + */ template <typename _Type> const _Type& get() const; /** - * \brief Get index in template list of type actually contained + * \brief Get index in template list of type actually contained, starting at 1 at the end of the template list * - * Get index in template list of type actually contained + * Get index in template list of type actually contained, starting at 1 at the end of the template list * * @return Index of contained type */ @@ -214,7 +219,7 @@ public: private: inline bool hasValue() const { - return valueType_ < TypesTupleSize::value; + return valueType_ <= TypesTupleSize::value; } template<typename _U> @@ -223,7 +228,7 @@ private: template<typename _U> void set( _U&& value, const bool clear); - template<typename _FriendType> + template<typename > friend struct TypeWriter; template<typename ... _FriendTypes> friend struct AssignmentVisitor; @@ -233,6 +238,8 @@ private: friend struct PartialEqualsVisitor; template<typename ... _FriendTypes> friend struct InputStreamReadVisitor; + template<class Variant, typename ... _FTypes> + friend struct ApplyVoidIndexVisitor; uint8_t valueType_; typename std::aligned_storage<maxSize>::type valueStorage_; diff --git a/src/CommonAPI/SerializableVariant.hpp b/src/CommonAPI/SerializableVariant.hpp index 3760118..2919638 100644 --- a/src/CommonAPI/SerializableVariant.hpp +++ b/src/CommonAPI/SerializableVariant.hpp @@ -15,6 +15,35 @@ namespace CommonAPI { +template<class Variant, typename ... _Types> +struct ApplyVoidIndexVisitor; + +template<class Variant> +struct ApplyVoidIndexVisitor<Variant> { + static const uint8_t index = 0; + + static + void visit(Variant&, uint8_t&) { + //won't be called + assert(false); + } +}; + +template<class Variant, typename _Type, typename ... _Types> +struct ApplyVoidIndexVisitor<Variant, _Type, _Types...> { + static const uint8_t index = ApplyVoidIndexVisitor<Variant, + _Types...>::index + 1; + + static void visit(Variant& var, uint8_t& ind) { + if (ind == index) { + new (&var.valueStorage_) _Type(); + var.valueType_ = index; + } else { + ApplyVoidIndexVisitor<Variant, _Types...>::visit(var, ind); + } + } +}; + template<class Visitor, class Variant, typename ... _Types> struct ApplyVoidVisitor; @@ -87,7 +116,7 @@ struct ApplyBoolVisitor<Visitor, Variant, _Type, _Types...> { } }; -/*template<uint8_t size> +template<uint8_t size> struct DeleteVisitor { public: DeleteVisitor(typename std::aligned_storage<size>::type& storage) : @@ -96,31 +125,11 @@ public: template<typename _Type> void operator()(const _Type&) const { - _Type thing = (reinterpret_cast<const _Type&>(storage_)); - thing.~_Type(); + (reinterpret_cast<const _Type *>(&storage_))->~_Type(); } private: typename std::aligned_storage<size>::type& storage_; -};*/ - -template<uint8_t size, typename ... _Types> -struct DeleteVisitor { -public: - DeleteVisitor(Variant<_Types ...>& storage) : - storage_(storage) - { - - } - - template<typename _Type> - void operator()(const _Type& value) const { - value.~_Type(); - //storage_.get<_Type>().~_Type(); - } - -private: - Variant<_Types...>& storage_; }; struct TypeOutputStreamWriteVisitor { @@ -326,6 +335,7 @@ struct TypeIndex<_Type, _Types...> { template<typename ... _Types> Variant<_Types...>::Variant() : valueType_(TypesTupleSize::value) { + ApplyVoidIndexVisitor<Variant<_Types...>, _Types...>::visit(*this, valueType_); } template<typename ... _Types> @@ -335,24 +345,32 @@ Variant<_Types...>::Variant(const Variant& fromVariant) { } template<typename ... _Types> -Variant<_Types...>::Variant(Variant&& fromVariant) { +Variant<_Types...>::Variant(Variant&& fromVariant) +{ AssignmentVisitor<_Types...> visitor(*this, false); ApplyVoidVisitor<AssignmentVisitor<_Types...> , Variant<_Types...>, _Types...>::visit(visitor, fromVariant); } +/*template<typename ... _Types> +Variant<_Types...>::Variant(Variant&& fromVariant) : + valueType_(std::move(fromVariant.valueType_)), + valueStorage_(std::move(fromVariant.valueStorage_)) +{ +}*/ + template<typename ... _Types> Variant<_Types...>::~Variant() { if (hasValue()) { - DeleteVisitor<maxSize, _Types...> visitor(*this); - ApplyVoidVisitor<DeleteVisitor<maxSize, _Types...>, Variant<_Types...>, _Types...>::visit(visitor, *this); + DeleteVisitor<maxSize> visitor(valueStorage_); + ApplyVoidVisitor<DeleteVisitor<maxSize>, Variant<_Types...>, _Types...>::visit(visitor, *this); } } template<typename ... _Types> void Variant<_Types...>::readFromInputStream(const uint8_t typeIndex, InputStream& inputStream) { if(hasValue()) { - DeleteVisitor<maxSize, _Types...> visitor(*this); - ApplyVoidVisitor<DeleteVisitor<maxSize, _Types...>, Variant<_Types...>, _Types...>::visit(visitor, *this); + DeleteVisitor<maxSize> visitor(valueStorage_); + ApplyVoidVisitor<DeleteVisitor<maxSize>, Variant<_Types...>, _Types...>::visit(visitor, *this); } valueType_ = typeIndex; InputStreamReadVisitor<_Types...> visitor(*this, inputStream); @@ -447,8 +465,8 @@ void Variant<_Types...>::set(const _U& value, const bool clear) { typedef typename TypeSelector<_U, _Types...>::type selected_type_t; if (clear) { - DeleteVisitor<maxSize, _Types...> visitor(*this); - ApplyVoidVisitor<DeleteVisitor<maxSize, _Types...>, Variant<_Types...>, _Types...>::visit(visitor, *this); + DeleteVisitor<maxSize> visitor(valueStorage_); + ApplyVoidVisitor<DeleteVisitor<maxSize>, Variant<_Types...>, _Types...>::visit(visitor, *this); } new (&valueStorage_) selected_type_t(std::move(value)); valueType_ = TypeIndex<_Types...>::template get<selected_type_t>(); @@ -462,8 +480,8 @@ void Variant<_Types...>::set(_U&& value, const bool clear) { selected_type_t&& any_container_value = std::move(value); if(clear) { - DeleteVisitor<maxSize, _Types...> visitor(*this); - ApplyVoidVisitor<DeleteVisitor<maxSize, _Types...>, Variant<_Types...>, _Types...>::visit(visitor, *this); + DeleteVisitor<maxSize> visitor(valueStorage_); + ApplyVoidVisitor<DeleteVisitor<maxSize>, Variant<_Types...>, _Types...>::visit(visitor, *this); } else { new (&valueStorage_) selected_type_t(std::move(any_container_value)); } diff --git a/src/test/VariantTest.cpp b/src/test/VariantTest.cpp index 441a288..4d7e5e1 100755 --- a/src/test/VariantTest.cpp +++ b/src/test/VariantTest.cpp @@ -15,6 +15,52 @@ class VariantTest: public ::testing::Test { } }; + +struct test1: CommonAPI::SerializableStruct { + int a; + std::string b; + + test1() = default; + test1(const int& a, const std::string& b) : + a(a), b(b) { + } + + void readFromInputStream(CommonAPI::InputStream& inputStream) { + + } + + void writeToOutputStream(CommonAPI::OutputStream& outputStream) const { + + } + + static inline void writeToTypeOutputStream(CommonAPI::TypeOutputStream& typeOutputStream) { + } + +}; + +struct test2: CommonAPI::SerializableStruct { + int a; + std::string b; + + test2() = default; + test2(const int& a, const std::string& b) : + a(a), b(b) { + } + + void readFromInputStream(CommonAPI::InputStream& inputStream) { + + } + + void writeToOutputStream(CommonAPI::OutputStream& outputStream) const { + + } + + static inline void writeToTypeOutputStream(CommonAPI::TypeOutputStream& typeOutputStream) { + } + +}; + + TEST_F(VariantTest, VariantTestPack) { int fromInt = 5; @@ -70,6 +116,11 @@ TEST_F(VariantTest, VariantTestPack) { std::cout << "myInt is std::string = " << "\n"; EXPECT_FALSE(myVariant.isType<std::string>()); + Variant<int, double, std::string> movedVariant = std::move(myVariant); + std::cout << "myMovedInt is int = " << " (" << std::boolalpha << movedVariant.isType<int>() << ")\n"; + EXPECT_TRUE(movedVariant.isType<int>()); + EXPECT_EQ(fromInt, movedVariant.get<int>()); + const double& myDouble = myVariantf.get<double>(); std::cout << "myDouble = " << myDouble << "\n"; @@ -85,6 +136,14 @@ TEST_F(VariantTest, VariantTestPack) { std::cout << "myStringCopy = " << myStringCopy << "\n"; delete myVariants; + + test1 sourceStruct = {1, "a"}; + + Variant<test1, test2> complexSource = sourceStruct; + + Variant<test1, test2> complexTarget = complexSource; + EXPECT_EQ(1, complexTarget.get<test1>().a); + } int main(int argc, char** argv) { |