qxLib
generic_span.h
Go to the documentation of this file.
1 /**
2 
3  @file generic_span.h
4  @author Khrapov
5  @date 20.11.2022
6  @copyright © Nick Khrapov, 2022. All right reserved.
7 
8 **/
9 #pragma once
10 
11 #include <qx/meta/qualifiers.h>
12 
13 #include <functional>
14 
15 namespace qx
16 {
17 
19 {
20  template<class... args_t>
21  using function_type = std::function<args_t...>;
22 };
23 
24 /**
25 
26  @class generic_span
27  @brief Same as std::span, but may be used with any container with forward iterators
28  @details The class can be used to use any container to iterate over its elements
29  Useful when used in virtual methods
30  Does not own the container
31  The container should not be changed until the end of the iteration
32  May be much slower then std::span when the size of sbo of std::function
33  is smaller then sizeof 2 iterators of this container
34  (libcpp: 16, ligcxx: 16, MSVC: 56)
35  @tparam T - container value type
36  @author Khrapov
37  @date 20.11.2022
38 
39 **/
40 template<class T, class traits_t = default_generic_span_traits>
42 {
43  template<class container_t>
44  using container_value = std::remove_reference_t<decltype(*std::declval<container_t>().begin())>;
45 
46  template<class target_t>
47  using qualified_type = copy_qualifiers_t<std::remove_reference_t<std::remove_pointer_t<T>>, target_t>;
48 
49 public:
50  using traits = traits_t;
51  template<class... args_t>
52  using function_type = typename traits_t::template function_type<args_t...>;
53  using generator_type = function_type<T*()>;
54 
55  using element_type = T;
56  using value_type = std::remove_cv_t<T>;
57  using pointer = T*;
58  using reference = T&;
59 
60  class iterator
61  {
62  public:
63  using value_type = T;
64  using pointer = T*;
65  using reference = T&;
66  using difference_type = std::ptrdiff_t;
67  using size_type = size_t;
68  using iterator_category = std::forward_iterator_tag;
69  using iterator_concept = std::forward_iterator_tag;
70 
71  public:
72  constexpr iterator() noexcept = default;
73  constexpr iterator(const iterator&) noexcept = default;
74  constexpr iterator(generator_type generator, size_type nIndex) noexcept;
75  [[nodiscard]] constexpr reference operator*() const noexcept;
76  [[nodiscard]] constexpr pointer operator->() const noexcept;
77  constexpr iterator& operator++() noexcept;
78  [[nodiscard]] constexpr iterator operator++(int) noexcept;
79  constexpr bool operator!=(const iterator& r) const noexcept;
80  constexpr bool operator==(const iterator& r) const noexcept;
81  constexpr operator void*() const noexcept;
82 
83  private:
84  generator_type m_Generator;
85  size_type m_nIndex = 0;
86  };
87 
88 public:
89  generic_span() noexcept = default;
90  generic_span(generic_span&&) noexcept = default;
91  generic_span(const generic_span&) noexcept = default;
92 
93  /**
94  @brief generic_span object constructor
95  @tparam container_t - any container, which adapter satisfies forward iterator concept
96  @param container - container instance. container must not be edited until adapter death
97  **/
98  template<class container_t>
99  generic_span(container_t& container) noexcept;
100 
101  /**
102  @brief generic_span object constructor
103  @tparam container_t - any container, which adapter satisfies forward iterator concept
104  @param container - container instance. container must not be edited until adapter death
105  @param valueAdapter - function which transforms Container::value_type to T*
106  **/
107  template<class container_t>
108  generic_span(
109  container_t& container,
110  function_type<reference(qualified_type<container_value<container_t>>&)> valueAdapter) noexcept;
111 
112  /**
113  @brief operator=
114  @tparam container_t - any container, which adapter satisfies forward iterator concept
115  @param container - container instance. container must not be edited until adapter death
116  @retval - this object reference
117  **/
118  template<class container_t>
119  generic_span& operator=(container_t& container) noexcept;
120 
121  generic_span& operator=(generic_span&&) noexcept = default;
122  generic_span& operator=(const generic_span&) noexcept = default;
123 
124  /**
125  @brief Check if span is empty
126  @retval - true if empty
127  **/
128  bool empty() const noexcept;
129 
130  /**
131  @brief Return iterator to beginning
132  @retval - iterator to beginning
133  **/
134  iterator begin() const noexcept;
135 
136  /**
137  @brief Return iterator to end
138  @retval - iterator to end
139  **/
140  iterator end() const noexcept;
141 
142  /**
143  @brief Return const iterator to beginning
144  @retval - const iterator to beginning
145  **/
146  iterator cbegin() const noexcept;
147 
148  /**
149  @brief Return const iterator to end
150  @retval - const iterator to end
151  **/
152  iterator cend() const noexcept;
153 
154 private:
155  /**
156  @brief Create initial generator
157  @tparam container_t - any container, which adapter satisfies forward iterator concept
158  @tparam adapter_t - adapter callable type
159  @param container - container instance. container must not be edited until adapter death
160  @param adapter - function which transforms Container::value_type to T*
161  @retval - values generator
162  **/
163  template<class container_t, class adapter_t>
164  static generator_type create_initial_generator(container_t&& container, adapter_t adapter) noexcept;
165 
166 private:
167  generator_type m_InitialGenerator;
168 };
169 
170 } // namespace qx
171 
172 #include <qx/patterns/generic_span.inl>
Same as std::span, but may be used with any container with forward iterators.
Definition: generic_span.h:42
iterator begin() const noexcept
Return iterator to beginning.