Ability to copy union and to set union type 10/31210/5
authorMateusz Malicki <m.malicki2@samsung.com>
Tue, 2 Dec 2014 14:01:32 +0000 (15:01 +0100)
committerMateusz Malicki <m.malicki2@samsung.com>
Mon, 8 Dec 2014 11:17:42 +0000 (12:17 +0100)
[Feature]       Ability to copy union and to set union type
[Cause]         Need to copy and add new union elements
[Solution]      Use of boost::any class; add isSet and set<T> methods
[Verification]  Build, install, run scs tests

Change-Id: I61e3211c27e62af93b36a5309e50ebaf90ab70ad

src/config/fields-union.hpp

index 8f4d997..57e54a0 100644 (file)
@@ -26,7 +26,8 @@
 #define CONFIG_FIELDS_UNION_HPP
 
 #include "config/fields.hpp"
-#include <memory>
+#include <utility>
+#include <boost/any.hpp>
 #include <cassert>
 
 /**
  *
  *  Usage:
  *   Config config;
- *   if (config.is<Foo>()) {
- *       Foo& foo = config.as<Foo>();
- *       // ...
- *   }
- *   if (config.is<int>())) {
- *       int field = config.as<int>();
- *       // ...
+ *   // ...
+ *   if (config.isSet()) {
+ *      if (config.is<Foo>()) {
+ *          Foo& foo = config.as<Foo>();
+ *          // ...
+ *      }
+ *      if (config.is<int>())) {
+ *          int field = config.as<int>();
+ *          // ...
+ *      }
+ *   } else {
+ *     // Config is not set
+ *     Foo foo({"some string"});
+ *     config.set(foo);
+ *     config.set(std::move(foo));
+ *     config.set(Foo({"some string"}));
  *   }
  */
 
 
 #define CONFIG_DECLARE_UNION(...)                                                               \
-    struct TypeWrapperBase                                                                      \
-    {                                                                                           \
-        virtual ~TypeWrapperBase() {}                                                           \
-    };                                                                                          \
+private:                                                                                        \
+    boost::any mConfigDeclareField__;                                                           \
                                                                                                 \
-    template<typename Class>                                                                    \
-    struct TypeWrapper : TypeWrapperBase                                                        \
-    {                                                                                           \
-        Class value;                                                                            \
-        ~TypeWrapper() {}                                                                       \
-    };                                                                                          \
-                                                                                                \
-    std::unique_ptr<TypeWrapperBase> mConfigDeclareField__;                                     \
+    template<typename Visitor>                                                                  \
+    void visitOption(Visitor& v, const std::string& name) {                                     \
+        GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__)                                      \
+    }                                                                                           \
+    template<typename Visitor>                                                                  \
+    void visitOption(Visitor& v, const std::string& name) const {                               \
+        GENERATE_CODE(GENERATE_UNION_VISIT_CONST__, __VA_ARGS__)                                \
+    }                                                                                           \
+    std::string getOptionName() const {                                                         \
+        GENERATE_CODE(GENERATE_UNION_NAME__, __VA_ARGS__)                                       \
+        return std::string();                                                                   \
+    }                                                                                           \
+public:                                                                                         \
                                                                                                 \
     template<typename Visitor>                                                                  \
     void accept(Visitor v) {                                                                    \
             v.visit("type", name);                                                              \
             visitOption(v, name);                                                               \
         } else {                                                                                \
-           /* Unsupported type in config file */                                                \
+           /* Unsupported type */                                                               \
         }                                                                                       \
     }                                                                                           \
                                                                                                 \
-    template<typename Visitor>                                                                  \
-    void visitOption(Visitor& v, const std::string& name) {                                     \
-        GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__)                                      \
-    }                                                                                           \
-    template<typename Visitor>                                                                  \
-    void visitOption(Visitor& v, const std::string& name) const {                               \
-        GENERATE_CODE(GENERATE_UNION_VISIT_CONST__, __VA_ARGS__)                                \
-    }                                                                                           \
-    std::string getOptionName() const {                                                         \
-        GENERATE_CODE(GENERATE_UNION_NAME__, __VA_ARGS__)                                       \
-        return std::string();                                                                   \
-    }                                                                                           \
-                                                                                                \
     template<typename Type>                                                                     \
     bool is() const {                                                                           \
-        return dynamic_cast<TypeWrapper<Type>*>(mConfigDeclareField__.get()) != NULL;           \
+        return boost::any_cast<Type>(&mConfigDeclareField__) != NULL;                           \
     }                                                                                           \
     template<typename Type>                                                                     \
     Type& as() {                                                                                \
-        assert(mConfigDeclareField__.get());                                                    \
-        return dynamic_cast<TypeWrapper<Type>&>(*mConfigDeclareField__.get()).value;            \
+        assert(!mConfigDeclareField__.empty());                                                 \
+        return boost::any_cast<Type&>(mConfigDeclareField__);                                   \
     }                                                                                           \
     template<typename Type>                                                                     \
     const Type& as() const {                                                                    \
-        assert(mConfigDeclareField__.get());                                                    \
-        return dynamic_cast<const TypeWrapper<Type>&>(*mConfigDeclareField__.get()).value;      \
-    }
+        assert(!mConfigDeclareField__.empty());                                                 \
+        return boost::any_cast<const Type&>(mConfigDeclareField__);                             \
+    }                                                                                           \
+    bool isSet() {                                                                              \
+        return !getOptionName().empty();                                                        \
+    }                                                                                           \
+    template<typename Type>                                                                     \
+    Type& set(Type&& src) {                                                                     \
+        mConfigDeclareField__ = std::forward<Type>(src);                                        \
+        return as<Type>();                                                                      \
+    }                                                                                           \
 
 #define GENERATE_CODE(MACRO, ...)                                                               \
     BOOST_PP_LIST_FOR_EACH(MACRO, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
 
 #define GENERATE_UNION_VISIT__(r, _, TYPE_)                                                     \
     if (#TYPE_ == name) {                                                                       \
-        mConfigDeclareField__.reset(new TypeWrapper<TYPE_>());                                  \
-        v.visit("value", as<TYPE_>());                                                          \
+        v.visit("value", set(std::move(TYPE_())));                                              \
     }
 
 #define GENERATE_UNION_VISIT_CONST__(r, _, TYPE_)                                               \