Fork Vasum on GitHub Official Vasum Wiki on Tizen.org
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
fields-union.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Contact: Mateusz Malicki (m.malicki2@samsung.com)
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License
17  */
18 
25 #ifndef CARGO_FIELDS_UNION_HPP
26 #define CARGO_FIELDS_UNION_HPP
27 
28 #include "cargo/fields.hpp"
29 #include "cargo/exception.hpp"
30 
31 #include <utility>
32 #include <boost/any.hpp>
33 
34 class DisableMoveAnyWrapper : public boost::any
35 {
36  public:
39  : boost::any(static_cast<const boost::any&>(any)) {};
42  static_cast<boost::any&>(*this) = static_cast<const boost::any&>(any);
43  return *this;
44  }
45 };
46 
107 #define CARGO_DECLARE_UNION(...) \
108 private: \
109  DisableMoveAnyWrapper mCargoDeclareField; \
110  \
111  template<typename Visitor> \
112  void visitOption(Visitor& v, const std::string& name) { \
113  GENERATE_CODE(GENERATE_UNION_VISIT__, __VA_ARGS__) \
114  throw cargo::CargoException("Union type error. Unsupported type"); \
115  } \
116  template<typename Visitor> \
117  void visitOption(Visitor& v, const std::string& name) const { \
118  GENERATE_CODE(GENERATE_UNION_VISIT_CONST__, __VA_ARGS__) \
119  throw cargo::CargoException("Union type error. Unsupported type"); \
120  } \
121  std::string getOptionName() const { \
122  GENERATE_CODE(GENERATE_UNION_NAME__, __VA_ARGS__) \
123  return std::string(); \
124  } \
125  boost::any& getHolder() { \
126  return static_cast<boost::any&>(mCargoDeclareField); \
127  } \
128  const boost::any& getHolder() const { \
129  return static_cast<const boost::any&>(mCargoDeclareField); \
130  } \
131 public: \
132  \
133  template<typename Visitor> \
134  void accept(Visitor v) { \
135  std::string name; \
136  v.visit("type", name); \
137  visitOption(v, name); \
138  } \
139  \
140  template<typename Visitor> \
141  void accept(Visitor v) const { \
142  const std::string name = getOptionName(); \
143  if (name.empty()) { \
144  throw cargo::CargoException("Type is not set"); \
145  } \
146  v.visit("type", name); \
147  visitOption(v, name); \
148  } \
149  \
150  template<typename Type> \
151  bool is() const { \
152  return boost::any_cast<Type>(&getHolder()) != NULL; \
153  } \
154  template<typename Type> \
155  typename std::enable_if<!std::is_const<Type>::value, Type>::type& as() { \
156  if (getHolder().empty()) { \
157  throw cargo::CargoException("Type is not set"); \
158  } \
159  return boost::any_cast<Type&>(getHolder()); \
160  } \
161  template<typename Type> \
162  const Type& as() const { \
163  if (getHolder().empty()) { \
164  throw cargo::CargoException("Type is not set"); \
165  } \
166  return boost::any_cast<const Type&>(getHolder()); \
167  } \
168  bool isSet() { \
169  return !getOptionName().empty(); \
170  } \
171  template<typename Type> \
172  Type& set(const Type& src) { \
173  getHolder() = std::forward<const Type>(src); \
174  if (getOptionName().empty()) { \
175  throw cargo::CargoException("Unsupported type"); \
176  } \
177  return as<Type>(); \
178  } \
179 
180 #define GENERATE_CODE(MACRO, ...) \
181  BOOST_PP_LIST_FOR_EACH(MACRO, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
182 
183 #define GENERATE_UNION_VISIT__(r, _, TYPE_) \
184  if (#TYPE_ == name) { \
185  v.visit("value", set(std::move(TYPE_()))); \
186  return; \
187  }
188 
189 #define GENERATE_UNION_VISIT_CONST__(r, _, TYPE_) \
190  if (#TYPE_ == name) { \
191  v.visit("value", as<const TYPE_>()); \
192  return; \
193  }
194 
195 #define GENERATE_UNION_NAME__(r, _, TYPE_) \
196  if (is<TYPE_>()) { \
197  return #TYPE_; \
198  }
199 
200 #endif // CARGO_FIELDS_UNION_HPP
DisableMoveAnyWrapper & operator=(DisableMoveAnyWrapper &&any)=delete
DisableMoveAnyWrapper()
Definition: fields-union.hpp:37
DisableMoveAnyWrapper(const DisableMoveAnyWrapper &any)
Definition: fields-union.hpp:38
Exceptions for libcargo.
DisableMoveAnyWrapper & operator=(const DisableMoveAnyWrapper &any)
Definition: fields-union.hpp:41
Definition: fields-union.hpp:34