summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohannes Schanda <schanda@itestra.de>2013-05-29 23:13:34 +0200
committerJohannes Schanda <schanda@itestra.de>2013-05-29 23:13:34 +0200
commitbe635b51f6ad0b978a3aa8f7e1a167495b9f3b70 (patch)
treebbe1f0c4642942080e41a12209a3a50855c7b4b1 /src
parent447790b568b7d2710ae10ddeb16d57b19561757e (diff)
downloadgenivi-common-api-runtime-be635b51f6ad0b978a3aa8f7e1a167495b9f3b70.tar.gz
Corrected move constructor / initialisation of empty variant
Diffstat (limited to 'src')
-rw-r--r--src/CommonAPI/SerializableVariant.h15
-rw-r--r--src/CommonAPI/SerializableVariant.hpp80
-rwxr-xr-xsrc/test/VariantTest.cpp59
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) {