#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_) \