siplasplas
A library for C++ reflection and introspection
any.hpp
1 #ifndef SIPLASPLAS_TYPEERASURE_ANY_HPP
2 #define SIPLASPLAS_TYPEERASURE_ANY_HPP
3 
4 #include "simpleany.hpp"
5 #include "function.hpp"
6 #include "field.hpp"
7 #include <siplasplas/utility/hash.hpp>
8 
9 namespace cpp
10 {
11 
41 template<
42  typename Storage,
43  typename FunctionsStorage = Storage,
44  typename FunctionArgsStorage = FunctionsStorage,
45  typename AttributesStorage = FunctionsStorage
46 >
47 class Any : public SimpleAny<Storage>
48 {
49 public:
50  using Base = SimpleAny<Storage>;
52 
55 
56  template<typename Class, typename... Args>
57  static Any create(Args&&... args)
58  {
59  return SimpleAny<Storage>::template create<Class>(std::forward<Args>(args)...);
60  }
61 
62  class MethodProxy
63  {
64  public:
65  MethodProxy(Method& method, Any* this_) :
66  _method{&method},
67  _this{this_}
68  {}
69 
70  template<typename... Args>
71  auto operator()(Args&&... args)
72  {
73  return (*_method)(_this->getReference(), std::forward<Args>(args)...);
74  }
75 
76  template<typename... Args>
77  auto operator()(Args&&... args) const
78  {
79  return (*_method)(_this->getReference(), std::forward<Args>(args)...);
80  }
81 
82  template<typename Callable>
83  MethodProxy& operator=(Callable&& callable)
84  {
85  *_method = std::forward<Callable>(callable);
86  return *this;
87  }
88 
89  const Method& method() const
90  {
91  return *_method;
92  }
93 
94  Method& method()
95  {
96  return *_method;
97  }
98 
99  private:
100  Method* _method;
101  Any* _this;
102  };
103 
104  class ConstMethodProxy
105  {
106  public:
107  ConstMethodProxy(const Method& method, const Any* this_) :
108  _method{&method},
109  _this{this_}
110  {}
111 
112  template<typename... Args>
113  auto operator()(Args&&... args) const
114  {
115  return (*_method)(_this->getReference(), std::forward<Args>(args)...);
116  }
117 
118  const Method& method() const
119  {
120  return *_method;
121  }
122 
123  private:
124  const Method* _method;
125  const Any* _this;
126  };
127 
128  class AttributeProxy
129  {
130  public:
131  AttributeProxy(Attribute& attribute, Any* this_) :
132  _attribute{&attribute},
133  _this{this_}
134  {}
135 
136  template<typename Invokable>
137  std::enable_if_t<
138  cpp::function_kind<std::decay_t<Invokable>>() == cpp::FunctionKind::MEMBER_OBJECT,
139  AttributeProxy&
140  >
141  operator=(Invokable&& invokable)
142  {
143  (*_attribute) = std::forward<Invokable>(invokable);
144  return *this;
145  }
146 
147  template<typename T>
148  std::enable_if_t<
149  cpp::function_kind<std::decay_t<T>>() != cpp::FunctionKind::MEMBER_OBJECT,
150  AttributeProxy&
151  >
152  operator=(T&& value)
153  {
154  get<std::decay_t<T>>() = std::forward<T>(value);
155  return *this;
156  }
157 
158  template<typename T>
159  T& get()
160  {
161  return _attribute->template getAs<T>(_this->simpleAny());
162  }
163 
164  template<typename T>
165  operator T&()
166  {
167  return get<T>();
168  }
169 
170  template<typename T>
171  const T& get() const
172  {
173  return _attribute->template getAs<T>(_this->simpleAny());
174  }
175 
176  template<typename T>
177  operator const T&() const
178  {
179  return get<T>();
180  }
181 
182  const Attribute& attribute() const
183  {
184  return *_attribute;
185  }
186 
187  Attribute& attribute()
188  {
189  return *_attribute;
190  }
191 
192  private:
193  Attribute* _attribute;
194  Any* _this;
195  };
196 
197  class ConstAttributeProxy
198  {
199  public:
200  ConstAttributeProxy(const Attribute& attribute, const Any* this_) :
201  _attribute{&attribute},
202  _this{this_}
203  {}
204 
205  template<typename T>
206  const T& get() const
207  {
208  return _attribute->template getAs<T>(_this->simpleAny());
209  }
210 
211  template<typename T>
212  operator const T&() const
213  {
214  return get<T>();
215  }
216 
217  const Attribute& attribute() const
218  {
219  return *_attribute;
220  }
221 
222  private:
223  const Attribute* _attribute;
224  const Any* _this;
225  };
226 
227 
237  MethodProxy operator()(const std::string& name)
238  {
239  return {_methods[name], this};
240  }
241 
251  ConstMethodProxy operator()(const std::string& name) const
252  {
253  SIPLASPLAS_ASSERT(hasMethod(name))("Class {} has no method named '{}'", Base::typeInfo().typeName(), name);
254  return {_methods[name], this};
255  }
256 
257  AttributeProxy operator[](const std::string& name)
258  {
259  return {_attributes[name], this};
260  }
261 
262  ConstAttributeProxy operator[](const std::string& name) const
263  {
264  SIPLASPLAS_ASSERT(hasAttribute(name))("Class {} has no attribute named '{}'", Base::typeInfo().typeName(), name);
265  return {_attributes[name], this};
266  }
267 
275  bool hasMethod(const std::string& name) const
276  {
277  auto it = _methods.find(name);
278 
279  if(it != _methods.end())
280  {
281  return !it->second.empty();
282  }
283  else
284  {
285  return false;
286  }
287  }
288 
296  bool hasAttribute(const std::string& name) const
297  {
298  auto it = _attributes.find(name);
299 
300  if(it != _attributes.end())
301  {
302  return !it->second.empty();
303  }
304  else
305  {
306  return false;
307  }
308  }
309 
314  {
315  return *static_cast<::cpp::SimpleAny<Storage>*>(this);
316  }
317 
321  const ::cpp::SimpleAny<Storage>& simpleAny() const
322  {
323  return *static_cast<::cpp::SimpleAny<Storage>*>(this);
324  }
325 
326 private:
329 };
330 
336 
342 
348 
354 
360 
366 
367 }
368 
369 #endif // SIPLASPLAS_TYPEERASURE_ANY_HPP
::cpp::SimpleAny< Storage > & simpleAny()
Returns the any object as a SimpleAny.
Definition: any.hpp:313
SimpleAny & operator=(const T &value)
Assigns a value of type T.
Definition: simpleany.hpp:535
const ::cpp::SimpleAny< Storage > & simpleAny() const
Returns the any object as a SimpleAny.
Definition: any.hpp:321
Definition: canary_allocator.hpp:7
Stores a type erased member object pointer.
Definition: field.hpp:25
cpp::typeerasure::TypeInfo typeInfo() const
Returns the type information of the hosted type.
Definition: simpleany.hpp:503
bool hasMethod(const std::string &name) const
Checks if the object has a method with a given name.
Definition: any.hpp:275
std::unordered_map< Key, Value, Hash< Key >> HashTable
std::unordered_map alias using cpp::Hash as hash.
Definition: hash.hpp:240
ConstMethodProxy operator()(const std::string &name) const
Gives access to an object method.
Definition: any.hpp:251
Implements a type-erased value container with minimal value semantics requirements.
Definition: simpleany.hpp:15
MethodProxy operator()(const std::string &name)
Gives access to an object method.
Definition: any.hpp:237
bool hasAttribute(const std::string &name) const
Checks if the object has an attribute with a given name.
Definition: any.hpp:296
const char * typeName() const
Returns the name of the type.
Definition: typeinfo.hpp:134
Implements a type-erased object container with support for dynamic method and attribute invokation...
Definition: any.hpp:47
Stores a type-erased callable of any signature and kind.
Definition: function.hpp:58
#define SIPLASPLAS_ASSERT(...)
Defines an assertion expression.
Definition: assert.hpp:212