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/memory/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  static constexpr bool bPreserveContents = false;
66  static constexpr size_type growth_strategy(size_type nOldCapacity) noexcept
67  {
68  return nOldCapacity;
69  }
70  };
71 
72 public:
74  using base_type = base_t;
75 
76 public:
77  /**
78  @brief sbo_poly object constructor
79  @tparam derived_t - type inherited from base_t
80  @param object - an object to store
81  **/
82  template<sbo_poly_assignable_c<base_t> derived_t>
83  sbo_poly(derived_t object) noexcept;
84 
85  sbo_poly(sbo_poly&& other) noexcept;
86  ~sbo_poly() noexcept;
87 
88  /**
89  @brief operator=
90  @tparam derived_t - type inherited from base_t
91  @param object - an object to store
92  @retval - this object reference
93  **/
94  template<sbo_poly_assignable_c<base_t> derived_t>
95  sbo_poly& operator=(derived_t object) noexcept;
96 
97  sbo_poly& operator=(sbo_poly&& other) noexcept;
98 
99  /**
100  @brief Assign a new object to this SBO
101  @tparam derived_t - type inherited from base_t
102  @param object - an object to store
103  **/
104  template<sbo_poly_assignable_c<base_t> derived_t>
105  void assign(derived_t object) noexcept;
106 
107 
108  base_t* operator->() noexcept;
109  const base_t* operator->() const noexcept;
110 
111  /**
112  @brief Get object reference. Always valid.
113  @retval - object reference
114  **/
115  base_t& get() noexcept;
116 
117  /**
118  @brief Get object reference. Always valid.
119  @retval - object reference
120  **/
121  const base_t& get() const noexcept;
122 
123 private:
124  sbo_bytes_type m_Data;
125  void (*m_Assigner)(sbo_bytes_type& from, sbo_bytes_type& to) = nullptr;
126  void (*m_Deleter)(sbo_bytes_type& object) = nullptr;
127 };
128 
129 } // namespace qx
130 
131 #include <qx/memory/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