Virtual Testbed
Ship dynamics simulator for extreme conditions
traits.hh
1 #ifndef VTESTBED_GUILE_TRAITS_HH
2 #define VTESTBED_GUILE_TRAITS_HH
3 
4 #include <vtestbed/guile/wrapper.hh>
5 
6 namespace vtb {
7 
8  namespace guile {
9 
10  template <class T>
11  class Traits {
12 
13  public:
14  using value_type = T;
15 
16  public:
17  static void define();
18  static SCM type();
19  static inline SCM make() { return make_object<T>(type()); }
20  static inline SCM make(const T& rhs) {
21  return make_object<T>(type(), new Aspect<T>(rhs));
22  }
23  static inline SCM make(T&& rhs) {
24  return make_object<T>(type(), new Aspect<T>(std::move(rhs)));
25  }
26 
27  };
28 
29  template <class T>
30  class Traits<std::unique_ptr<T>> {
31 
32  public:
33  using value_type = std::unique_ptr<T>;
34 
35  public:
36  static void define();
37  static SCM type();
38  static inline SCM make() { return make_object<T>(type()); }
39  static inline SCM make(value_type&& rhs) {
40  return make_object<T>(type(), std::move(rhs));
41  }
42 
43  };
44 
45  template <>
46  class Traits<std::any> {
47 
48  public:
49  using value_type = std::any;
50 
51  public:
52  static void define();
53  static SCM type();
54  static inline SCM make() { return make_object<value_type>(type()); }
55  static inline SCM make(const value_type& rhs) {
56  return make_object(type(), rhs);
57  }
58  static inline SCM make(value_type&& rhs) {
59  return make_object(type(), std::move(rhs));
60  }
61 
62  };
63 
64  template <class T> inline Wrapper<T>*
65  get_wrapper(SCM object) {
66  scm_assert_foreign_object_type(Traits<T>::type(), object);
67  auto* wrapper = to_wrapper<T>(object);
68  if (!wrapper->get()) { throw std::invalid_argument("pointer is null"); }
69  return wrapper;
70  }
71 
72  template <> inline Wrapper<std::any>*
73  get_wrapper(SCM object) {
74  scm_assert_foreign_object_type(Traits<std::any>::type(), object);
75  auto* wrapper = to_wrapper<std::any>(object);
76  if (!wrapper->get().has_value()) { throw std::invalid_argument("pointer is null"); }
77  return wrapper;
78  }
79 
80  template <class T> inline T*
81  get_object(SCM object) {
82  SCM type = scm_class_of(object);
83  T* ptr = nullptr;
84  if (type == Traits<T>::type()) {
85  ptr = to_wrapper<T>(object)->get();
86  } else if (type == Traits<std::any>::type()) {
87  auto* wrapper = to_wrapper<std::any>(object);
88  if (!wrapper->get().has_value()) {
89  throw std::invalid_argument("pointer is null");
90  }
91  if (wrapper->get().type() != typeid(T*)) {
92  throw std::invalid_argument("bad guile object type");
93  }
94  ptr = std::any_cast<T*>(wrapper->get());
95  } else {
96  throw std::invalid_argument("bad guile object type");
97  }
98  if (!ptr) { throw std::invalid_argument("pointer is null"); }
99  return ptr;
100  }
101 
102  template <class T> inline T*
103  get_pointer(SCM object) {
104  scm_assert_foreign_object_type(Traits<std::any>::type(), object);
105  auto* wrapper = to_wrapper<std::any>(object);
106  if (!wrapper->get().has_value()) { throw std::invalid_argument("pointer is null"); }
107  if (wrapper->get().type() != typeid(T*)) {
108  throw std::invalid_argument("bad guile object type");
109  }
110  return std::any_cast<T*>(wrapper->get());
111  }
112 
113  }
114 
115 }
116 
117 #endif // vim:filetype=cpp
Aspect that extends Guile-unaware classes and provides a pointer to the corresponding wrapper object.
Definition: wrapper.hh:16
Main namespace.
Definition: convert.hh:9