qxLib
rtti.h
Go to the documentation of this file.
1 /**
2 
3  @file rtti.h
4  @brief RTTI system based on polymorphism
5  @details Using qx::rtti_root and QX_RTTI_CLASS
6  will let you to use RTTI advantages without enabling
7  RTTI in compiler's flags
8  common logic is taken from
9  https://github.com/qualab/xakep-RTTI (Vladimir Kerimov, qualab)
10  @author Khrapov
11  @date 24.08.2020
12  @copyright © Nick Khrapov, 2021. All right reserved.
13 
14 **/
15 #pragma once
16 
18 #include <qx/macros/common.h>
20 #include <qx/meta/tuple_utils.h>
21 #include <qx/rtti/class_id.h>
23 
24 #include <array>
25 #include <span>
26 
27 namespace qx
28 {
29 
30 // utility class to let you use std::derived_from
32 {
33  QX_COPYMOVABLE(rtti_pure_base);
34 
35  template<class naming_strategy_t>
36  friend class rtti_root;
37 
38 public:
39  auto operator<=>(const rtti_pure_base&) const = default;
40 
41 private:
42  rtti_pure_base() = default;
43 };
44 
45 /**
46 
47  @class rtti_root
48  @brief RTTI root class
49  @details All other classes must be inherited from this class
50  to allow you to use RTTI functions
51  @tparam naming_strategy_t - \see rtti_naming_strategy.h
52  @author Khrapov
53  @date 10.09.2021
54 
55 **/
56 template<class naming_strategy_t = rtti_naming_strategy_class_name>
57 class rtti_root : public rtti_pure_base
58 {
59  QX_COPYMOVABLE(rtti_root);
60 
61 public:
62  using base_class_type = rtti_root;
64  using this_class_type = rtti_root;
65  using inheritance_tuple_type = std::tuple<this_class_type>;
66  using naming_strategy_type = naming_strategy_t;
67 
68 public:
69  rtti_root() noexcept = default;
70 
71  auto operator<=>(const rtti_root&) const = default;
72 
73  template<class T>
74  bool is_derived_from() const noexcept
75  {
76  constexpr class_id typeId = T::get_class_id_static();
77  return _is_base_id(typeId) || typeId == get_class_id();
78  }
79 
80  template<class T>
81  bool is() const noexcept
82  {
83  return get_class_id() == T::get_class_id_static();
84  }
85 
86  bool is(string_view svClassName) const noexcept
87  {
88  return svClassName == get_class_name();
89  }
90 
91  bool is(class_id id) const noexcept
92  {
93  return id == get_class_id();
94  }
95 
96  virtual bool is_derived_from_id(class_id id) const noexcept
97  {
98  return is_derived_from_id_static(id);
99  }
100 
101  static constexpr bool is_derived_from_id_static(class_id id) noexcept
102  {
103  return id == get_class_id_static();
104  }
105 
106  static constexpr string_view get_class_name_static() noexcept
107  {
108  return naming_strategy_type::get_name(type_strings<this_class_type>::get_signature());
109  }
110 
111  virtual string_view get_class_name() const noexcept
112  {
113  return get_class_name_static();
114  }
115 
116  static constexpr class_id get_class_id_static() noexcept
117  {
118  constexpr class_id id = class_id::create<this_class_type>();
119  return id;
120  }
121 
122  virtual class_id get_class_id() const noexcept
123  {
124  return get_class_id_static();
125  }
126 
127  virtual std::span<const class_id> get_inheritance_sequence() const = 0;
128 
129 protected:
130  virtual ~rtti_root() noexcept = default;
131 
132  virtual bool _is_base_id(class_id idBase) const noexcept
133  {
134  return idBase == get_class_id_static();
135  }
136 };
137 
138 namespace filters
139 {
140 
141 template<class T>
142 constexpr auto is_derived_from = [](const auto& value)
143 {
144  return value.template is_derived_from<T>();
145 };
146 
147 template<class T>
148 constexpr auto is = [](const auto& value)
149 {
150  return value.template is<T>();
151 };
152 
153 } // namespace filters
154 
155 
156 /**
157  @def QX_RTTI_CLASS
158  @brief Macro for every class inherited from class with QX_RTTI_BASE_CLASS macro
159  @param thisClass - this class name
160  @param ... - super class name (must implement QX_RTTI_CLASS or QX_RTTI_BASE_CLASS macro)
161 **/
162 #define QX_RTTI_CLASS(thisClass, ...) \
163  \
164 public: \
165  using this_class_type = thisClass; \
166  using super_class_type = __VA_ARGS__; \
167  using base_class_type = typename super_class_type::base_class_type; \
168  using inheritance_tuple_type = \
169  qx::tuple_utils::join_t<typename super_class_type::inheritance_tuple_type, this_class_type>; \
170  \
171 public: \
172  static constexpr bool is_derived_from_id_static(qx::class_id id) noexcept \
173  { \
174  return id == get_class_id_static() || super_class_type::is_derived_from_id_static(id); \
175  } \
176  virtual bool is_derived_from_id(qx::class_id id) const noexcept override \
177  { \
178  static_assert(std::is_same_v<std::remove_cvref_t<decltype(*this)>, this_class_type>); \
179  return is_derived_from_id_static(id); \
180  } \
181  static constexpr qx::string_view get_class_name_static() noexcept \
182  { \
183  return base_class_type::naming_strategy_type::get_name(qx::type_strings<this_class_type>::get_signature()); \
184  } \
185  virtual qx::class_id get_class_id() const noexcept override \
186  { \
187  return get_class_id_static(); \
188  } \
189  static constexpr qx::class_id get_class_id_static() noexcept \
190  { \
191  constexpr qx::class_id id = qx::class_id::create<this_class_type>(); \
192  return id; \
193  } \
194  virtual qx::string_view get_class_name() const noexcept override \
195  { \
196  return get_class_name_static(); \
197  } \
198  virtual std::span<const qx::class_id> get_inheritance_sequence() const override \
199  { \
200  static constexpr auto ids = []() \
201  { \
202  std::array<qx::class_id, std::tuple_size_v<inheritance_tuple_type>> ids_; \
203  qx::tuple_utils::iterate<inheritance_tuple_type>( \
204  [&ids_]<class T, size_t I>() \
205  { \
206  ids_[I] = T::get_class_id_static(); \
207  }); \
208  return ids_; \
209  }(); \
210  return ids; \
211  } \
212  \
213 protected: \
214  virtual bool _is_base_id(qx::class_id base_id) const noexcept override \
215  { \
216  return base_id == super_class_type::get_class_id_static() || super_class_type::_is_base_id(base_id); \
217  } \
218  \
219 private: \
220  QX_EMPTY_MACRO
221 
222 } // namespace qx
Class id, unique for each class using qx rtti system.
Definition: class_id.h:27
RTTI root class.
Definition: rtti.h:58
The class allows you to get strings with information about the type, including its full name,...
Definition: type_strings.h:37
Contains naming strategies for qx::rtti_root class.
Contains utils for working with std::tuple.