qxLib
sbo_poly.h
Go to the documentation of this file.
1 /**
2 
3  @file sbo_poly.h
4  @author Khrapov
5  @date 20.12.2025
6  @copyright © Nick Khrapov, 2025. All right reserved.
7 
8 **/
9 #pragma once
10 
11 #include <qx/sbo/sbo_bytes.h>
12 
13 #include <type_traits>
14 
15 namespace qx
16 {
17 
18 // Check that the derived type is suitable for storing in sbo_poly
19 template<class T, class base_t>
20 concept sbo_poly_assignable_c =
21  std::is_base_of_v<base_t, T> && std::is_move_constructible_v<T> && std::is_destructible_v<T>;
22 
23 // Check that the derived type fits into the SBO buffer
24 template<class sbo_poly_t, sbo_poly_assignable_c<typename sbo_poly_t::base_type> derived_t>
26 {
27  static constexpr bool value = sizeof(derived_t) <= sbo_poly_t::sbo_bytes_type::nBufferSize;
28 };
29 
30 template<class sbo_poly_t, sbo_poly_assignable_c<typename sbo_poly_t::base_type> derived_t>
31 constexpr bool sbo_poly_fittable_type_v = sbo_poly_fittable_type<sbo_poly_t, derived_t>::value;
32 
33 // If you have several inheritors, you can check that they all fit into your SBO
34 template<class sbo_poly_t, class... args_t>
36 {
37  static constexpr bool value = ((sbo_poly_fittable_type_v<sbo_poly_t, args_t>) && ...);
38 };
39 
40 template<class sbo_poly_t, class... args_t>
41 constexpr bool sbo_poly_fittable_types_v = sbo_poly_fittable_types<sbo_poly_t, args_t...>::value;
42 
43 /**
44 
45  @class sbo_poly
46  @brief Small Buffer Object for polymorphic classes.
47  @details If the inherited class fits into the specified buffer, it stores it in place;
48  if not, it allocates memory for it.
49  Allows you to increase cache locality when storing in containers.
50  @tparam base_t - base class type, you'll be able to work with each element through its interface
51  @tparam nSBOSize_ - the size of the whole SBO type, including internal data
52  @author Khrapov
53  @date 24.12.2025
54 
55 **/
56 template<class base_t, size_t nSBOSize_>
57 class sbo_poly
58 {
59  struct sbo_poly_traits
60  {
61  using size_type = size_t;
62  static_assert(nSBOSize_ > sizeof(void*));
63  static constexpr size_type nSBOSize = nSBOSize_ - 2 * sizeof(void*);
64  static constexpr bool bShrinkToFitWhenSmall = true;
65  };
66 
67 public:
69  using base_type = base_t;
70 
71 public:
72  /**
73  @brief sbo_poly object constructor
74  @tparam derived_t - type inherited from base_t
75  @param object - an object to store
76  **/
77  template<sbo_poly_assignable_c<base_t> derived_t>
78  sbo_poly(derived_t object) noexcept;
79 
80  sbo_poly(sbo_poly&& other) noexcept;
81  ~sbo_poly() noexcept;
82 
83  /**
84  @brief operator=
85  @tparam derived_t - type inherited from base_t
86  @param object - an object to store
87  @retval - this object reference
88  **/
89  template<sbo_poly_assignable_c<base_t> derived_t>
90  sbo_poly& operator=(derived_t object) noexcept;
91 
92  sbo_poly& operator=(sbo_poly&& other) noexcept;
93 
94  /**
95  @brief Assign a new object to this SBO
96  @tparam derived_t - type inherited from base_t
97  @param object - an object to store
98  **/
99  template<sbo_poly_assignable_c<base_t> derived_t>
100  void assign(derived_t object) noexcept;
101 
102 
103  base_t* operator->() noexcept;
104  const base_t* operator->() const noexcept;
105 
106  /**
107  @brief Get object reference. Always valid.
108  @retval - object reference
109  **/
110  base_t& get() noexcept;
111 
112  /**
113  @brief Get object reference. Always valid.
114  @retval - object reference
115  **/
116  const base_t& get() const noexcept;
117 
118 private:
119  sbo_bytes_type m_Data;
120  void (*m_Assigner)(sbo_bytes_type& from, sbo_bytes_type& to) = nullptr;
121  void (*m_Deleter)(sbo_bytes_type& object) = nullptr;
122 };
123 
124 } // namespace qx
125 
126 #include <qx/sbo/sbo_poly.inl>
Small Buffer Object for polymorphic classes.
Definition: sbo_poly.h:58
base_t & get() noexcept
Get object reference. Always valid.
Definition: sbo_poly.inl:127
sbo_poly(derived_t object) noexcept
sbo_poly object constructor
Definition: sbo_poly.inl:15
sbo_poly & operator=(derived_t object) noexcept
operator=
void assign(derived_t object) noexcept
Assign a new object to this SBO.
Definition: sbo_poly.inl:94