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  iterator() noexcept = default;
73  iterator(const iterator&) noexcept = default;
74  iterator(generator_type generator, size_type nIndex) noexcept;
75  [[nodiscard]] reference operator*() const noexcept;
76  [[nodiscard]] pointer operator->() const noexcept;
77  iterator& operator++() noexcept;
78  [[nodiscard]] iterator operator++(int) noexcept;
79  bool operator!=(const iterator& r) const noexcept;
80  bool operator==(const iterator& r) const noexcept;
81  operator void*() const noexcept;
82  operator bool() const noexcept;
83 
84  private:
85  generator_type m_Generator;
86  size_type m_nIndex = 0;
87  };
88 
89 public:
90  generic_span() noexcept = default;
91  generic_span(generic_span&&) noexcept = default;
92  generic_span(const generic_span&) noexcept = default;
93 
94  /**
95  @brief generic_span object constructor
96  @tparam container_t - any container, which adapter satisfies forward iterator concept
97  @param container - container instance. container must not be edited until adapter death
98  **/
99  template<class container_t>
100  generic_span(container_t& container) noexcept;
101 
102  /**
103  @brief generic_span object constructor
104  @tparam container_t - any container, which adapter satisfies forward iterator concept
105  @param container - container instance. container must not be edited until adapter death
106  @param valueAdapter - function which transforms Container::value_type to T*
107  **/
108  template<class container_t>
109  generic_span(
110  container_t& container,
111  function_type<reference(qualified_type<container_value<container_t>>&)> valueAdapter) noexcept;
112 
113  /**
114  @brief operator=
115  @tparam container_t - any container, which adapter satisfies forward iterator concept
116  @param container - container instance. container must not be edited until adapter death
117  @retval - this object reference
118  **/
119  template<class container_t>
120  generic_span& operator=(container_t& container) noexcept;
121 
122  generic_span& operator=(generic_span&&) noexcept = default;
123  generic_span& operator=(const generic_span&) noexcept = default;
124 
125  /**
126  @brief Check if span is empty
127  @retval - true if empty
128  **/
129  bool empty() const noexcept;
130 
131  /**
132  @brief Return iterator to beginning
133  @retval - iterator to beginning
134  **/
135  iterator begin() const noexcept;
136 
137  /**
138  @brief Return iterator to end
139  @retval - iterator to end
140  **/
141  iterator end() const noexcept;
142 
143  /**
144  @brief Return const iterator to beginning
145  @retval - const iterator to beginning
146  **/
147  iterator cbegin() const noexcept;
148 
149  /**
150  @brief Return const iterator to end
151  @retval - const iterator to end
152  **/
153  iterator cend() const noexcept;
154 
155 private:
156  /**
157  @brief Create initial generator
158  @tparam container_t - any container, which adapter satisfies forward iterator concept
159  @tparam adapter_t - adapter callable type
160  @param container - container instance. container must not be edited until adapter death
161  @param adapter - function which transforms Container::value_type to T*
162  @retval - values generator
163  **/
164  template<class container_t, class adapter_t>
165  static generator_type create_initial_generator(container_t&& container, adapter_t adapter) noexcept;
166 
167 private:
168  generator_type m_InitialGenerator;
169 };
170 
171 } // namespace qx
172 
173 #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.