cgv
reflection_handler.h
1 #pragma once
2 
3 #include <vector>
4 #include <cgv/type/info/type_name.h>
5 #include <cgv/utils/convert.h>
6 #include <cgv/utils/token.h>
7 #include <cgv/type/traits/method_pointer.h>
8 #include <cgv/type/info/type_id.h>
9 
10 #include "self_reflection_tag.h"
11 #include "reflection_traits_info.h"
12 
13 #include "lib_begin.h"
14 
16 namespace cgv {
18  namespace reflect {
19 
24 {
25  virtual void call_void(void* instance,
26  const std::vector<abst_reflection_traits*>& param_value_traits,
27  const std::vector<const void*>& param_value_ptrs,
28  const std::vector<std::string>& param_type_names,
29  const abst_reflection_traits* result_traits = 0,
30  void* result_value_ptr = 0,
31  const std::string& result_type = "") = 0;
32 };
33 
34 template <int i, int n, typename M>
35 struct method_parameter_traits_helper
36 {
37  static void fill_vector(std::vector<abst_reflection_traits*>& param_value_traits)
38  {
39  param_value_traits.push_back(reflection_traits_info<typename cgv::type::traits::method_pointer_argument_list<M,i>::type>::traits_type().clone());
40  if (i+1 < n)
41  method_parameter_traits_helper<i+1,n,M>::fill_vector(param_value_traits);
42  }
43 };
44 
45 template <int i, typename M>
46 struct method_parameter_traits_helper<i,i,M>
47 {
48  static void fill_vector(std::vector<abst_reflection_traits*>& param_value_traits)
49  {
50  }
51 };
52 
54 template <typename M>
55 struct method_interface_impl;
56 
62 class CGV_API reflection_handler
63 {
64 #ifndef REFLECT_TRAITS_WITH_DECLTYPE
65  template <typename B, typename RB>
66  bool reflect_base_impl(B& base_ref, const RB&);
67  template <typename T, unsigned n, typename RT>
68  bool reflect_const_array_impl(const std::string& member_name, T (&member_ref)[n], const RT&);
69  template <typename T, typename RT>
70  bool reflect_vector_impl(const std::string& member_name, std::vector<T>& member_ref, const RT&);
71 #endif
72 public:
73  template <typename T>
74  friend bool reflect_enum(reflection_handler& rh, const std::string& name, T& instance, const std::string& declarations);
75  template <typename T>
76  friend bool reflect_string(reflection_handler& rh, const std::string& name, T& instance);
77  friend struct detail;
80  enum GroupTraversal { GT_TERMINATE = -3, GT_SKIP = -2, GT_COMPLETE = -1 };
83  static std::string group_traversal_name(GroupTraversal gt);
85  enum GroupKind { GK_NO_GROUP, GK_BASE_CLASS, GK_STRUCTURE, GK_VECTOR, GK_ARRAY, GK_POINTER };
87  static const char* group_kind_name(GroupKind gk);
89  static bool is_array_kind(GroupKind gk);
91 protected:
94  GroupTraversal process_structural_group_begin(GroupKind gk, const std::string& member_name, GroupTraversal gt);
97  bool group_end(GroupKind gk);
99  template <typename T, typename RT, typename D>
100  bool self_reflect_member(const std::string& member_name, T& member_ref, const RT&, const D&, bool hard_cast)
101  {
102  RT rt;
103  switch (process_structural_group_begin(GK_STRUCTURE, member_name, GroupTraversal(reflect_group_begin(GK_STRUCTURE, member_name, &member_ref, &rt)))) {
104  case GT_TERMINATE : return false;
105  case GT_COMPLETE :
106  if (hard_cast)
107  return static_cast<D&>(member_ref).D::self_reflect(*this) && group_end(GK_STRUCTURE);
108  else {
109  D& d = static_cast<D&>(member_ref);
110  return d.self_reflect(*this) && group_end(GK_STRUCTURE);
111  }
112  default: return true;
113  }
114  }
116  int reflect_array_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr, abst_reflection_traits* rt, unsigned grp_size);
118 
121  struct nesting_info
123  {
127  const std::string* name;
129  unsigned idx;
131  nesting_info(GroupKind _group_kind = GK_NO_GROUP, const std::string* _name = 0, unsigned _idx = 0) : group_kind(_group_kind), name(_name), idx(_idx) {};
132  };
134  std::vector<nesting_info> nesting_info_stack;
136 
139 
151  virtual int reflect_group_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr, abst_reflection_traits* rt, unsigned grp_size = -1);
153 
154  virtual void reflect_group_end(GroupKind group_kind);
157  virtual bool reflect_member_void(const std::string& member_name, void* member_ptr, abst_reflection_traits* rt) = 0;
160  virtual bool reflect_method_void(const std::string& method_name, method_interface* mi_ptr,
161  abst_reflection_traits* return_traits, const std::vector<abst_reflection_traits*>& param_value_traits) = 0;
163 
164 public:
166  virtual ~reflection_handler();
167 
170  virtual bool is_creative() const;
179  template <typename T>
180  bool reflect_member(const std::string& member_name, T& member_ref, bool hard_cast = false);
189  template <typename M>
190  bool reflect_method(const std::string& method_name, M m);
192  template <typename B>
193  bool reflect_base(B& base_ref);
195  template <typename T, unsigned n>
196  bool reflect_member(const std::string& member_name, T (&member_ref)[n]);
198  template <typename T>
199  bool reflect_member(const std::string& member_name, std::vector<T>& member_ref);
201 
204  template <typename T>
205  bool reflect_member(const std::string& member_name, T*& member_ref);
207  template <typename T, typename S>
208  bool reflect_array(const std::string& member_name, T*& member_ref, S& size);
209 };
210 
211 
212 struct detail {
213 #ifndef REFLECT_TRAITS_WITH_DECLTYPE
214  template <typename T, ReflectionTraitsKind K>
215  struct reflect_member_impl
216  {
217  template <bool has_external, typename RT>
218  struct reflect_impl {
219  static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, const RT&, bool hard_cast) {
220  RT rt;
221  return rh->reflect_member_void(member_name, &member_ref, &rt);
222  }
223  };
224  template <typename RT>
225  struct reflect_impl<true,RT> {
226  static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, const RT&, bool hard_cast) {
227  RT rt;
228  return rh->self_reflect_member(member_name, member_ref, rt, static_cast<typename RT::external_self_reflect_type&>(member_ref), hard_cast);
229  }
230  };
231  template <typename RT>
232  static bool reflect_RT(reflection_handler* rh, const std::string& member_name, T& member_ref, const RT& rt, bool hard_cast) {
233  return reflect_impl<RT::has_external,RT>::reflect(rh, member_name, member_ref, rt, hard_cast);
234  }
235  static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
236  return reflect_RT(rh, member_name, member_ref, get_reflection_traits(member_ref), hard_cast);
237  }
238  };
239 
240  template <typename T> struct reflect_member_impl<T,RTK_STD_TYPE>
241  {
242  static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
243  typename reflection_traits_info<T>::traits_type rt;
244  return rh->reflect_member_void(member_name, &member_ref, &rt);
245  }
246  };
247 #else
248  template <typename T, ReflectionTraitsKind K>
249  struct reflect_member_impl
250  {
251  static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
252  typename reflection_traits_info<T>::traits_type rt;
253  return rh->reflect_member_void(member_name, &member_ref, &rt);
254  }
255  };
256 
257  template <typename T> struct reflect_member_impl<T,RTK_EXTERNAL_SELF_REFLECT>
258  {
259  static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
260  typename reflection_traits_info<T>::traits_type rt;
261  return rh->self_reflect_member(member_name, member_ref, rt, static_cast<typename reflection_traits_info<T>::traits_type::external_self_reflect_type&>(member_ref), hard_cast);
262  }
263  };
264 #endif
265  template <typename T> struct reflect_member_impl<T,RTK_SELF_REFLECT>
266  {
267  static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
268  typename reflection_traits_info<T>::traits_type rt;
269  return rh->self_reflect_member(member_name, member_ref, rt, member_ref, hard_cast);
270  }
271  };
272 
273  template <typename M, typename R>
274  struct reflect_method_impl {
275  static bool reflect(reflection_handler* rh, const std::string& method_name, M m)
276  {
277  static std::vector<abst_reflection_traits*> param_value_traits;
278  static method_interface_impl<M> mi(m);
279  if (param_value_traits.size() != cgv::type::traits::method_pointer<M>::nr_arguments)
280  method_parameter_traits_helper<0,cgv::type::traits::method_pointer<M>::nr_arguments,M>::fill_vector(param_value_traits);
281  typename reflection_traits_info<R>::traits_type rt;
282  return rh->reflect_method_void(method_name, &mi, &rt, param_value_traits);
283  }
284  };
285  template <typename M>
286  struct reflect_method_impl<M,void> {
287  static bool reflect(reflection_handler* rh, const std::string& method_name, M m)
288  {
289  static std::vector<abst_reflection_traits*> param_value_traits;
290  static method_interface_impl<M> mi(m);
291  if (param_value_traits.size() != cgv::type::traits::method_pointer<M>::nr_arguments)
292  method_parameter_traits_helper<0,cgv::type::traits::method_pointer<M>::nr_arguments,M>::fill_vector(param_value_traits);
293  return rh->reflect_method_void(method_name, &mi, 0, param_value_traits);
294  }
295  };
296 
297 #ifndef REFLECT_TRAITS_WITH_DECLTYPE
298  template <bool use_get, typename B>
299  struct reflect_base_dispatch { static bool reflect(reflection_handler* rh, B& base_ref) {
300  return rh->reflect_base_impl(base_ref, typename reflection_traits_info<B>::traits_type()); } };
301  template <typename B>
302  struct reflect_base_dispatch<true,B> { static bool reflect(reflection_handler* rh, B& base_ref) {
303  return rh->reflect_base_impl(base_ref, get_reflection_traits(base_ref)); } };
304 
305  template <bool use_get, typename T, unsigned n>
306  struct reflect_const_array_dispatch { static bool reflect(reflection_handler* rh, const std::string& member_name, T (&member_ref)[n]) {
307  return rh->reflect_const_array_impl(member_name, member_ref, typename reflection_traits_info<T>::traits_type()); } };
308  template <typename T, unsigned n>
309  struct reflect_const_array_dispatch<true,T,n> { static bool reflect(reflection_handler* rh, const std::string& member_name, T (&member_ref)[n]) {
310  return rh->reflect_const_array_impl(member_name, member_ref, get_reflection_traits(T())); } };
311 
312  template <bool use_get, typename T>
313  struct reflect_vector_dispatch { static bool reflect(reflection_handler* rh, const std::string& member_name, std::vector<T>& member_ref) {
314  return rh->reflect_vector_impl(member_name, member_ref, typename reflection_traits_info<T>::traits_type()); } };
315  template <typename T>
316  struct reflect_vector_dispatch<true,T> { static bool reflect(reflection_handler* rh, const std::string& member_name, std::vector<T>& member_ref) {
317  return rh->reflect_vector_impl(member_name, member_ref, get_reflection_traits(T())); } };
318 #endif
319 };
320 
321 
322 template <typename T>
323 bool reflection_handler::reflect_member(const std::string& member_name, T& member_ref, bool hard_cast)
324 {
325 #ifdef REFLECT_TRAITS_WITH_DECLTYPE
326  return detail::reflect_member_impl<T, reflection_traits_info<T>::kind>::reflect(this, member_name, member_ref, hard_cast);
327 #else
328  return detail::reflect_member_impl<T, reflection_traits_info<T>::kind>::reflect(this, member_name, member_ref, hard_cast);
329 #endif
330 }
331 
332 template <typename M>
333 bool reflection_handler::reflect_method(const std::string& method_name, M m)
334 {
335  return detail::reflect_method_impl<M,typename cgv::type::traits::method_pointer<M>::return_type>::reflect(this, method_name, m);
336 }
337 
338 #ifdef REFLECT_TRAITS_WITH_DECLTYPE
339 template <typename B>
340 bool reflection_handler::reflect_base(B& base_ref)
341 {
343 #else
344 template <typename B, typename RB>
345 bool reflection_handler::reflect_base_impl(B& base_ref, const RB&)
346 {
347  RB rt;
348 #endif
349  switch (process_structural_group_begin(GK_BASE_CLASS, "", GroupTraversal(reflect_group_begin(GK_BASE_CLASS, "", &base_ref, &rt)))) {
350  case GT_TERMINATE : return false;
351  case GT_COMPLETE : return reflect_member("", base_ref, true) && group_end(GK_BASE_CLASS);
352  default: return true;
353  }
354 }
355 #ifndef REFLECT_TRAITS_WITH_DECLTYPE
356 template <typename B>
358 {
359  return detail::reflect_base_dispatch<reflection_traits_info<B>::use_get,B>::reflect(this,base_ref);
360 }
361 #endif
362 
363 
364 
365 
366 
367 #ifdef REFLECT_TRAITS_WITH_DECLTYPE
368 template <typename T, unsigned n>
369 bool reflection_handler::reflect_member(const std::string& member_name, T (&member_ref)[n])
370 {
372 #else
373 template <typename T, unsigned n, typename RT>
374 bool reflection_handler::reflect_const_array_impl(const std::string& member_name, T (&member_ref)[n], const RT&)
375 {
376  RT rt;
377 #endif
378  int grp_tra = reflect_array_begin(GK_ARRAY, member_name, member_ref, &rt, n);
379  if (grp_tra == GT_TERMINATE || grp_tra == GT_SKIP)
380  return grp_tra == GT_SKIP;
381  bool res = true;
382  if (grp_tra == GT_COMPLETE) {
383  for (nesting_info_stack.back().idx=0; res && nesting_info_stack.back().idx<n; ++nesting_info_stack.back().idx)
384  res = reflect_member("", member_ref[nesting_info_stack.back().idx]);
385  group_end(GK_ARRAY);
386  }
387  else {
388  res = reflect_member("", member_ref[grp_tra]);
389  nesting_info_stack.pop_back();
390  }
391  return res;
392 }
393 #ifndef REFLECT_TRAITS_WITH_DECLTYPE
394 template <typename T, unsigned n>
395 bool reflection_handler::reflect_member(const std::string& member_name, T (&member_ref)[n])
396 {
397  return detail::reflect_const_array_dispatch<reflection_traits_info<T>::use_get,T,n>::reflect(this,member_name,member_ref);
398 }
399 #endif
400 
401 #ifdef REFLECT_TRAITS_WITH_DECLTYPE
402 template <typename T>
403 bool reflection_handler::reflect_member(const std::string& member_name, std::vector<T>& member_ref)
404 {
406 #else
407 template <typename T, typename RT>
408 bool reflection_handler::reflect_vector_impl(const std::string& member_name, std::vector<T>& member_ref, const RT&)
409 {
410  RT rt;
411 #endif
412  int grp_tra = reflect_array_begin(GK_VECTOR, member_name, &member_ref, &rt, (unsigned)member_ref.size());
413  if (grp_tra == GT_TERMINATE || grp_tra == GT_SKIP)
414  return grp_tra == GT_SKIP;
415  bool res = true;
416  if (grp_tra == GT_COMPLETE) {
417  unsigned size = (unsigned)member_ref.size();
418  res = reflect_member("size", size);
419  if (member_ref.size() != size)
420  member_ref.resize(size);
421  for (nesting_info_stack.back().idx=0; res && nesting_info_stack.back().idx<size; ++nesting_info_stack.back().idx)
422  res = reflect_member("", member_ref[nesting_info_stack.back().idx]);
423  group_end(GK_VECTOR);
424  }
425  else {
426  res = reflect_member("", member_ref[grp_tra]);
427  nesting_info_stack.pop_back();
428  }
429  return res;
430 }
431 #ifndef REFLECT_TRAITS_WITH_DECLTYPE
432 template <typename T>
433 bool reflection_handler::reflect_member(const std::string& member_name, std::vector<T>& member_ref)
434 {
435  return detail::reflect_vector_dispatch<reflection_traits_info<T>::use_get,T>::reflect(this, member_name, member_ref);
436 }
437 #endif
438 
442 template <typename T>
443 bool reflection_handler::reflect_member(const std::string& member_name, T*& member_ref)
444 {
446  GroupTraversal gt = reflect_group_begin(GK_POINTER, member_name, &member_ref, &rt);
447  switch (gt) {
448  case GT_TERMINATE : return false;
449  case GT_SKIP : return true;
450  case GT_COMPLETE : break;
451  default:
452  std::cerr << "group traversal " << group_traversal_name(gt) << " not allowed on pointer group " << member_name << "!" << std::endl;
453  return false;
454  }
455  nesting_info_stack.push_back(nesting_info(GK_POINTER, &member_name));
456  unsigned pointer_type = (member_ref == 0 ? 0 : 1);
457  unsigned pointer_type_tmp = pointer_type;
458  bool res = reflect_member("pointer_type", pointer_type_tmp);
459  if (res) {
460  if (pointer_type_tmp != pointer_type) {
461  if (pointer_type != 0)
462  delete member_ref;
463  if (pointer_type_tmp == 0)
464  member_ref = 0;
465  else
466  member_ref = new T();
467  }
468  if (pointer_type_tmp != 0)
469  res = reflect_member(*member_ref);
470  }
471  group_end(GK_POINTER);
472  return res;
473 }
475 template <typename T, typename S>
476 bool reflection_handler::reflect_array(const std::string& member_name, T*& member_ref, S& size)
477 {
479  int grp_tra = reflect_array_begin(GK_ARRAY, member_name, member_ref, &rt, size);
480  if (grp_tra == GT_TERMINATE || grp_tra == GT_SKIP)
481  return grp_tra == GT_SKIP;
482  bool res = true;
483  if (grp_tra == GT_COMPLETE) {
484  unsigned tmp_size = size;
485  res = reflect_member("size", tmp_size);
486  if (size != tmp_size) {
487  T* tmp = member_ref;
488  member_ref = new T[tmp_size];
489  if (tmp) {
490  for (unsigned i=0; i<tmp_size && i < size; ++i)
491  member_ref[i] = tmp[i];
492  delete [] tmp;
493  }
494  size = tmp_size;
495  }
496  for (nesting_info_stack.back().idx=0; res && nesting_info_stack.back().idx<size; ++nesting_info_stack.back().idx)
497  res = reflect_member("", member_ref[nesting_info_stack.back().idx]);
498  group_end(GK_ARRAY);
499  }
500  else {
501  res = reflect_member("", member_ref[grp_tra]);
502  nesting_info_stack.pop_back();
503  }
504  return res;
505 }
506 
507  }
508 }
509 
510 #include <cgv/config/lib_end.h>
cgv::reflect::reflection_handler::reflect_base
bool reflect_base(B &base_ref)
reflect a base class with its members
Definition: reflection_handler.h:357
cgv::reflect::reflection_handler::reflect_member
bool reflect_member(const std::string &member_name, T &member_ref, bool hard_cast=false)
Definition: reflection_handler.h:323
cgv::reflect::abst_reflection_traits
abstract interface for type reflection with basic type management and optional string conversion
Definition: reflection_traits.h:24
cgv::reflect::reflection_handler::group_end
bool group_end(GroupKind gk)
updates the nesting info at the end of group and always returns true
Definition: reflection_handler.cxx:75
cgv::reflect::method_interface
Definition: reflection_handler.h:24
cgv::reflect::reflection_traits_info
the reflection_traits_info defines compile time information about reflection_traits for a given type ...
Definition: reflection_traits_info.h:54
cgv::reflect::reflection_handler::GroupKind
GroupKind
different support group types
Definition: reflection_handler.h:85
cgv::reflect::reflection_handler::nesting_info::name
const std::string * name
pointer to type name for base class groups and member name otherwise
Definition: reflection_handler.h:127
cgv::reflect::reflection_handler::reflect_method
bool reflect_method(const std::string &method_name, M m)
Definition: reflection_handler.h:333
cgv::reflect::reflection_handler::GroupTraversal
GroupTraversal
different values for group traversal strategy
Definition: reflection_handler.h:81
cgv::reflect::reflection_handler::nesting_info::idx
unsigned idx
current element index for vector and array groups
Definition: reflection_handler.h:129
cgv::reflect::reflection_handler
Definition: reflection_handler.h:63
cgv::reflect::reflection_handler::nesting_info::group_kind
GroupKind group_kind
group kind of nesting level
Definition: reflection_handler.h:125
cgv::reflect::reflection_handler::nesting_info_stack
std::vector< nesting_info > nesting_info_stack
stack of nesting_info used during the reflection process
Definition: reflection_handler.h:134
cgv::math::reflect
vec< T > reflect(const vec< T > &v, const vec< T > &n)
calculates the reflected direction of v; n is the normal of the reflecting surface
Definition: vec.h:822
cgv::reflect::reflection_handler::reflect_group_begin
virtual int reflect_group_begin(GroupKind group_kind, const std::string &group_name, void *group_ptr, abst_reflection_traits *rt, unsigned grp_size=-1)
abstract interface to start reflection of a group of members.
Definition: reflection_handler.cxx:31
cgv::reflect::reflection_handler::nesting_info
for each nesting during traversal a nesting info is pushed back to the end of the nesting info stack
Definition: reflection_handler.h:123
cgv::reflect::reflection_handler::reflect_array_begin
int reflect_array_begin(GroupKind group_kind, const std::string &group_name, void *group_ptr, abst_reflection_traits *rt, unsigned grp_size)
type independent functionality of array reflection
Definition: reflection_handler.cxx:82
cgv::reflect::reflection_handler::group_traversal_name
static std::string group_traversal_name(GroupTraversal gt)
return the group traversals as a string
Definition: reflection_handler.cxx:45
cgv::reflect::reflection_handler::reflect_array
bool reflect_array(const std::string &member_name, T *&member_ref, S &size)
reflect a dynamic array member of vector type
Definition: reflection_handler.h:476
cgv::type::traits::method_pointer
Definition: method_pointer.h:13
cgv::reflect::reflection_handler::reflect_method_void
virtual bool reflect_method_void(const std::string &method_name, method_interface *mi_ptr, abst_reflection_traits *return_traits, const std::vector< abst_reflection_traits * > &param_value_traits)=0
cgv::reflect::reflection_handler::self_reflect_member
bool self_reflect_member(const std::string &member_name, T &member_ref, const RT &, const D &, bool hard_cast)
implementation of reflection with internal or external self_reflect function
Definition: reflection_handler.h:100
cgv
the cgv namespace
Definition: vr_calib.cxx:9
cgv::reflect::reflection_handler::process_structural_group_begin
GroupTraversal process_structural_group_begin(GroupKind gk, const std::string &member_name, GroupTraversal gt)
type independent part of the reflect_group method that starts the group traversal
Definition: reflection_handler.cxx:61
cgv::type::invalid_type
use this type to mark the result of an invalid meta function
Definition: invalid_type.h:7
cgv::reflect::reflection_handler::reflect_member_void
virtual bool reflect_member_void(const std::string &member_name, void *member_ptr, abst_reflection_traits *rt)=0