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>
19 #include <qx/meta/tuple_utils.h>
20 #include <qx/rtti/class_id.h>
22 
23 #include <array>
24 #include <span>
25 
26 namespace qx
27 {
28 
29 // utility class to let you use std::derived_from
31 {
32  template<class naming_strategy_t>
33  friend class rtti_root;
34 
35 public:
36  auto operator<=>(const rtti_pure_base&) const = default;
37 
38 protected:
39  rtti_pure_base() = default;
40 };
41 
42 /**
43 
44  @class rtti_root
45  @brief RTTI root class
46  @details All other classes must be inherited from this class
47  to allow you to use RTTI functions
48  @tparam naming_strategy_t - \see rtti_naming_strategy.h
49  @author Khrapov
50  @date 10.09.2021
51 
52 **/
53 template<class naming_strategy_t = rtti_naming_strategy_class_name>
54 class rtti_root : public rtti_pure_base
55 {
56 public:
57  using base_class_type = rtti_root;
59  using this_class_type = rtti_root;
60  using inheritance_tuple_type = std::tuple<this_class_type>;
61  using naming_strategy_type = naming_strategy_t;
62 
63 public:
64  rtti_root() noexcept = default;
65  rtti_root(const rtti_root&) noexcept = default;
66  rtti_root(rtti_root&&) noexcept = default;
67 
68  template<class T>
69  bool is_derived_from() const noexcept
70  {
71  constexpr class_id typeId = T::get_class_id_static();
72  return _is_base_id(typeId) || typeId == get_class_id();
73  }
74 
75  template<class T>
76  bool is() const noexcept
77  {
78  return get_class_id() == T::get_class_id_static();
79  }
80 
81  bool is(string_view svClassName) const noexcept
82  {
83  return svClassName == get_class_name();
84  }
85 
86  bool is(class_id id) const noexcept
87  {
88  return id == get_class_id();
89  }
90 
91  virtual bool is_derived_from_id(class_id id) const noexcept
92  {
93  return is_derived_from_id_static(id);
94  }
95 
96  static constexpr bool is_derived_from_id_static(class_id id) noexcept
97  {
98  return id == get_class_id_static();
99  }
100 
101  static constexpr string_view get_class_name_static() noexcept
102  {
103  return naming_strategy_type::get_name(type_strings<this_class_type>::get_signature());
104  }
105 
106  virtual string_view get_class_name() const noexcept
107  {
108  return get_class_name_static();
109  }
110 
111  static constexpr class_id get_class_id_static() noexcept
112  {
113  return class_id::create<this_class_type>();
114  }
115 
116  virtual class_id get_class_id() const noexcept
117  {
118  return get_class_id_static();
119  }
120 
121  virtual std::span<const class_id> get_inheritance_sequence() const = 0;
122 
123  auto operator<=>(const rtti_root&) const = default;
124 
125 protected:
126  virtual ~rtti_root() noexcept = default;
127 
128  virtual bool _is_base_id(class_id idBase) const noexcept
129  {
130  return idBase == get_class_id_static();
131  }
132 };
133 
134 namespace filters
135 {
136 
137 template<class T>
138 constexpr auto rtti()
139 {
140  return [](const auto& value)
141  {
142  return value.template is_derived_from<T>();
143  };
144 }
145 
146 } // namespace filters
147 
148 
149 /**
150  @def QX_RTTI_CLASS
151  @brief Macro for every class inherited from class with QX_RTTI_BASE_CLASS macro
152  @param thisClass - this class name
153  @param ... - super class name (must implement QX_RTTI_CLASS or QX_RTTI_BASE_CLASS macro)
154 **/
155 #define QX_RTTI_CLASS(thisClass, ...) \
156  \
157 public: \
158  using this_class_type = thisClass; \
159  using super_class_type = __VA_ARGS__; \
160  using base_class_type = typename super_class_type::base_class_type; \
161  using inheritance_tuple_type = \
162  qx::tuple::join_t<typename super_class_type::inheritance_tuple_type, this_class_type>; \
163  \
164 public: \
165  static constexpr bool is_derived_from_id_static(qx::class_id id) noexcept \
166  { \
167  return id == get_class_id_static() || super_class_type::is_derived_from_id_static(id); \
168  } \
169  virtual bool is_derived_from_id(qx::class_id id) const noexcept override \
170  { \
171  static_assert(std::is_same_v<std::remove_cvref_t<decltype(*this)>, this_class_type>); \
172  return is_derived_from_id_static(id); \
173  } \
174  static constexpr qx::string_view get_class_name_static() noexcept \
175  { \
176  return base_class_type::naming_strategy_type::get_name(qx::type_strings<this_class_type>::get_signature()); \
177  } \
178  virtual qx::class_id get_class_id() const noexcept override \
179  { \
180  return get_class_id_static(); \
181  } \
182  static constexpr qx::class_id get_class_id_static() noexcept \
183  { \
184  return qx::class_id::create<this_class_type>(); \
185  } \
186  virtual qx::string_view get_class_name() const noexcept override \
187  { \
188  return get_class_name_static(); \
189  } \
190  virtual std::span<const qx::class_id> get_inheritance_sequence() const override \
191  { \
192  static constexpr auto ids = []() \
193  { \
194  std::array<qx::class_id, std::tuple_size_v<inheritance_tuple_type>> ids_; \
195  qx::tuple::iterate<inheritance_tuple_type>( \
196  [&ids_]<class T, size_t I>() \
197  { \
198  ids_[I] = T::get_class_id_static(); \
199  }); \
200  return ids_; \
201  }(); \
202  return ids; \
203  } \
204  \
205 protected: \
206  virtual bool _is_base_id(qx::class_id base_id) const noexcept override \
207  { \
208  return base_id == super_class_type::get_class_id_static() || super_class_type::_is_base_id(base_id); \
209  } \
210  \
211 private: \
212  QX_EMPTY_MACRO
213 
214 } // namespace qx
Class id, unique for each class using qx rtti system.
Definition: class_id.h:27
RTTI root class.
Definition: rtti.h:55
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.