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
*/
private:
inline bool hasValue() const {
- return valueType_ < TypesTupleSize::value;
+ return valueType_ <= TypesTupleSize::value;
}
template<typename _U>
template<typename _U>
void set( _U&& value, const bool clear);
- template<typename _FriendType>
+ template<typename >
friend struct TypeWriter;
template<typename ... _FriendTypes>
friend struct AssignmentVisitor;
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_;
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;
}
};
-/*template<uint8_t size>
+template<uint8_t size>
struct DeleteVisitor {
public:
DeleteVisitor(typename std::aligned_storage<size>::type& storage) :
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 {
template<typename ... _Types>
Variant<_Types...>::Variant() :
valueType_(TypesTupleSize::value) {
+ ApplyVoidIndexVisitor<Variant<_Types...>, _Types...>::visit(*this, valueType_);
}
template<typename ... _Types>
}
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);
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>();
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));
}
}
};
+
+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;
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";
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) {