VCCC  2024.05
VisualCamp Common C++ library
view_interface.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2023/12/24.
3 //
4 
5 #ifndef VCCC_RANGES_VIEW_INTERFACE_HPP_
6 #define VCCC_RANGES_VIEW_INTERFACE_HPP_
7 
8 #include <type_traits>
9 
12 #include "vccc/__iterator/prev.hpp"
15 #include "vccc/__ranges/begin.hpp"
17 #include "vccc/__ranges/cbegin.hpp"
18 #include "vccc/__ranges/cend.hpp"
20 #include "vccc/__ranges/empty.hpp"
21 #include "vccc/__ranges/end.hpp"
31 
32 namespace vccc {
33 namespace ranges {
34 namespace detail {
35 
36 template<typename T, typename = void>
37 struct is_empty_callable : std::false_type {};
38 
39 template<typename T>
40 struct is_empty_callable<T, void_t<decltype( ranges::empty(std::declval<T>()) )>> : std::true_type {};
41 
42 template<typename T, bool = has_typename_type<iterator<T>>::value>
43 struct check_vi_data : std::false_type {};
44 template<typename T>
45 struct check_vi_data<T, true> : contiguous_iterator<iterator_t<T>> {};
46 
47 template<
48  typename T,
49  bool =
50  conjunction<
51  forward_range<T>,
52  has_typename_type<iterator<T>>,
53  has_typename_type<sentinel<T>>
54  >::value
55 >
56 struct check_vi_size : std::false_type {};
57 
58 template<typename T>
59 struct check_vi_size<T, true> : sized_sentinel_for<sentinel_t<T>, iterator_t<T>> {};
60 
61 } // namespace detail
62 
65 
66 
77 template<typename Derived>
79  public:
80  static_assert(std::is_class<Derived>::value && std::is_same<Derived, std::remove_cv_t<Derived>>::value,
81  "Constraints not satisfied");
82 
83 
84  using _$vccc_derived = Derived;
85 
91  template<typename D = Derived, std::enable_if_t<
93  int> = 0>
94  constexpr bool empty() {
95  using namespace vccc::rel_ops;
96  return ranges::size(derived()) == 0;
97  }
98  template<typename D = Derived, std::enable_if_t<conjunction<
101  >::value, int> = 0>
102  constexpr bool empty() {
103  using namespace vccc::rel_ops;
104  return ranges::begin(derived()) == ranges::end(derived());
105  }
106 
107  template<typename D = Derived, std::enable_if_t<
109  int> = 0>
110  constexpr bool empty() const {
111  using namespace vccc::rel_ops;
112  return ranges::size(derived()) == 0;
113  }
114  template<typename D = Derived, std::enable_if_t<conjunction<
117  >::value, int> = 0>
118  constexpr bool empty() const {
119  using namespace vccc::rel_ops;
120  return ranges::begin(derived()) == ranges::end(derived());
121  }
123 
129  constexpr auto cbegin() {
130  return ranges::cbegin(derived());
131  }
132 
134  constexpr auto cbegin() const {
135  return ranges::cbegin(derived());
136  }
138 
139 
145  constexpr auto cend() {
146  return ranges::cend(derived());
147  }
148 
150  constexpr auto cend() const {
151  return ranges::cend(derived());
152  }
154 
160  template<typename D = Derived, std::enable_if_t<
162  int> = 0>
163  constexpr explicit operator bool() {
164  return !ranges::empty(derived());
165  }
166 
167  template<typename D = Derived, std::enable_if_t<
169  int> = 0>
170  constexpr explicit operator bool() const {
171  return !ranges::empty(derived());
172  }
174 
175 
181  template<typename D = Derived, std::enable_if_t<
183  int> = 0>
184  constexpr auto data() {
185  return vccc::to_address(ranges::begin(derived()));
186  }
187  template<typename D = Derived, std::enable_if_t<
189  int> = 0>
190  constexpr auto data() const {
191  return vccc::to_address(ranges::begin(derived()));
192  }
194 
195 
203  template<typename D = Derived, std::enable_if_t<
205  int> = 0>
206  constexpr auto size() {
207  using T = decltype(ranges::end(derived()) - ranges::begin(derived()));
208  return static_cast<T>(ranges::end(derived()) - ranges::begin(derived()));
209  }
210  template<typename D = Derived, std::enable_if_t<
212  int> = 0>
213  constexpr auto size() const {
214  using T = decltype(ranges::end(derived()) - ranges::begin(derived()));
215  return static_cast<T>(ranges::end(derived()) - ranges::begin(derived()));
216  }
218 
219 
227  template<typename D = Derived, std::enable_if_t<
229  int> = 0>
230  constexpr decltype(auto) front() {
231  return *ranges::begin(derived());
232  }
233  template<typename D = Derived, std::enable_if_t<
235  int> = 0>
236  constexpr decltype(auto) front() const {
237  return *ranges::begin(derived());
238  }
240 
241 
251  template<typename D = Derived, std::enable_if_t<conjunction<
254  >::value, int> = 0>
255  constexpr decltype(auto) back() {
256  return *ranges::prev(ranges::end(derived()));
257  }
258  template<typename D = Derived, std::enable_if_t<conjunction<
261  >::value, int> = 0>
262  constexpr decltype(auto) back() const {
263  return *ranges::prev(ranges::end(derived()));
264  }
266 
267 
276  template<typename R = Derived, std::enable_if_t<
278  int> = 0>
279  constexpr decltype(auto) operator[](range_difference_t<R> n) {
280  return ranges::begin(derived())[n];
281  }
282  template<typename R = const Derived, std::enable_if_t<
284  int> = 0>
285  constexpr decltype(auto) operator[](range_difference_t<R> n) const {
286  return ranges::begin(derived())[n];
287  }
289 
290  private:
291  constexpr const Derived& derived() const {
292  return static_cast<const Derived&>(*this);
293  }
294 
295  constexpr Derived& derived() {
296  return static_cast<Derived&>(*this);
297  }
298 };
299 
301 
302 } // namespace ranges
303 } // namespace vccc
304 
305 #endif // VCCC_RANGES_VIEW_INTERFACE_HPP_
helper class template for defining a view, using the curiously recurring template pattern
Definition: view_interface.hpp:78
constexpr auto size() const
Definition: view_interface.hpp:213
constexpr auto size()
Definition: view_interface.hpp:206
constexpr auto cbegin()
Definition: view_interface.hpp:129
Derived $vccc_derived
Definition: view_interface.hpp:84
constexpr auto cend()
Definition: view_interface.hpp:145
constexpr bool empty() const
Definition: view_interface.hpp:110
constexpr decltype(auto) back()
Definition: view_interface.hpp:255
constexpr auto data() const
Definition: view_interface.hpp:190
constexpr auto cbegin() const
Definition: view_interface.hpp:134
constexpr auto cend() const
Definition: view_interface.hpp:150
constexpr auto data()
Definition: view_interface.hpp:184
constexpr bool empty()
Definition: view_interface.hpp:94
constexpr decltype(auto) front()
Definition: view_interface.hpp:230
constexpr VCCC_INLINE_OR_STATIC detail::prev_niebloid prev
Definition: prev.hpp:53
constexpr T * to_address(T *p) noexcept
Definition: to_address.hpp:37
constexpr VCCC_INLINE_OR_STATIC detail::empty_niebloid empty
checks whether a range is empty
Definition: empty.hpp:116
constexpr VCCC_INLINE_OR_STATIC detail::cbegin_niebloid cbegin
returns an iterator to the beginning of a read-only range
Definition: cbegin.hpp:46
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
constexpr VCCC_INLINE_OR_STATIC detail::size_niebloid size
returns the size of a container or array
Definition: size.hpp:145
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
typename range_difference< R >::type range_difference_t
Used to obtain the difference type of the iterator type of range type R.
Definition: range_difference_t.hpp:41
constexpr VCCC_INLINE_OR_STATIC detail::cend_niebloid cend
returns a sentinel indicating the end of a read-only range
Definition: cend.hpp:46
void void_t
Definition: void_t.hpp:19
Definition: cxx20_rel_ops.hpp:17
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: conjunction.hpp:22
Definition: negation.hpp:23
specifies a range whose iterator type satisfies bidirectional_iterator
Definition: bidirectional_range.hpp:49
Definition: common_range.hpp:41
specifies a range whose iterator type satisfies forward_iterator
Definition: forward_range.hpp:47
specifies a range whose iterator type satisfies random_access_iterator
Definition: random_access_range.hpp:48
specifies that a range knows its size in constant time
Definition: sized_range.hpp:38