From 24abd8462353da9c7f0865fdfc268713c7402fd0 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Tue, 2 Dec 2014 15:01:32 +0100 Subject: [PATCH] Ability to copy union and to set union type [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 methods [Verification] Build, install, run scs tests Change-Id: I61e3211c27e62af93b36a5309e50ebaf90ab70ad --- src/config/fields-union.hpp | 91 ++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/config/fields-union.hpp b/src/config/fields-union.hpp index 8f4d997..57e54a0 100644 --- a/src/config/fields-union.hpp +++ b/src/config/fields-union.hpp @@ -26,7 +26,8 @@ #define CONFIG_FIELDS_UNION_HPP #include "config/fields.hpp" -#include +#include +#include #include /** @@ -64,31 +65,43 @@ * * Usage: * Config config; - * if (config.is()) { - * Foo& foo = config.as(); - * // ... - * } - * if (config.is())) { - * int field = config.as(); - * // ... + * // ... + * if (config.isSet()) { + * if (config.is()) { + * Foo& foo = config.as(); + * // ... + * } + * if (config.is())) { + * int field = config.as(); + * // ... + * } + * } 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 \ - struct TypeWrapper : TypeWrapperBase \ - { \ - Class value; \ - ~TypeWrapper() {} \ - }; \ - \ - std::unique_ptr mConfigDeclareField__; \ + template \ + void visitOption(Visitor& v, const std::string& name) { \ + GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__) \ + } \ + template \ + 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 \ void accept(Visitor v) { \ @@ -104,45 +117,39 @@ v.visit("type", name); \ visitOption(v, name); \ } else { \ - /* Unsupported type in config file */ \ + /* Unsupported type */ \ } \ } \ \ - template \ - void visitOption(Visitor& v, const std::string& name) { \ - GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__) \ - } \ - template \ - 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 \ bool is() const { \ - return dynamic_cast*>(mConfigDeclareField__.get()) != NULL; \ + return boost::any_cast(&mConfigDeclareField__) != NULL; \ } \ template \ Type& as() { \ - assert(mConfigDeclareField__.get()); \ - return dynamic_cast&>(*mConfigDeclareField__.get()).value; \ + assert(!mConfigDeclareField__.empty()); \ + return boost::any_cast(mConfigDeclareField__); \ } \ template \ const Type& as() const { \ - assert(mConfigDeclareField__.get()); \ - return dynamic_cast&>(*mConfigDeclareField__.get()).value; \ - } + assert(!mConfigDeclareField__.empty()); \ + return boost::any_cast(mConfigDeclareField__); \ + } \ + bool isSet() { \ + return !getOptionName().empty(); \ + } \ + template \ + Type& set(Type&& src) { \ + mConfigDeclareField__ = std::forward(src); \ + return as(); \ + } \ #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()); \ - v.visit("value", as()); \ + v.visit("value", set(std::move(TYPE_()))); \ } #define GENERATE_UNION_VISIT_CONST__(r, _, TYPE_) \ -- 2.7.4