KTL
Loading...
Searching...
No Matches
ipair.h
Go to the documentation of this file.
1#pragma once
2
3#include "../utility/empty_base.h"
4
5#include "ipair_fwd.h"
6
7#include <cstddef>
8#include <iterator>
9#include <optional>
10
11namespace ktl
12{
13 namespace detail
14 {
15 // has begin() && end()
16 template<typename T, typename = void>
17 struct is_iterable : std::false_type {};
18
19 template<typename T>
20 struct is_iterable<T, std::void_t<decltype(std::begin(std::declval<T&>())), decltype(std::end(std::declval<T&>()))>> : std::true_type {};
21
22 template<typename T>
24
25 // has operator--()
26 template<typename T, typename = void>
27 struct is_decrementable : std::false_type {};
28
29 template<typename T>
30 struct is_decrementable<T, std::void_t<decltype(--std::declval<T&>())>> : std::true_type {};
31
32 template<typename T>
34 }
35
36 template<typename K, typename V>
38 {
39 public:
40 template<typename A, typename B>
41 ipair_value(A&& key, B&& value) noexcept(std::is_nothrow_constructible_v<K, A> && std::is_nothrow_constructible_v<V, B>) :
42 first(std::forward<A>(key)),
43 second(std::forward<B>(value)) {}
44
46 {
47 return this;
48 }
49
50 const ipair_value* operator->() const noexcept
51 {
52 return this;
53 }
54
57 };
58
59 template<typename K, typename I>
61 {
62 private:
63 using V = decltype(*std::declval<I&>());
64
65 public:
66 //using iterator_category = typename std::iterator_traits<I>::iterator_category;
67 //using difference_type = typename std::iterator_traits<I>::difference_type;
71
72 public:
73 ipair_iterator(I&& iterator) noexcept(std::is_nothrow_default_constructible_v<K> && std::is_nothrow_move_constructible_v<I>) :
74 m_Iterator(std::move(iterator)),
75 m_Index{} {}
76
77 value_type operator*() const noexcept(std::is_nothrow_constructible_v<value_type, K, I> && noexcept(*std::declval<I&>()))
78 {
79 return value_type(m_Index, *m_Iterator);
80 }
81
82 value_type operator->() const noexcept(std::is_nothrow_constructible_v<value_type, K, I> && noexcept(*std::declval<I&>()))
83 {
84 return value_type(m_Index, *m_Iterator);
85 }
86
87 ipair_iterator& operator++() noexcept(noexcept(++std::declval<K&>()) && noexcept(++std::declval<I&>()))
88 {
89 ++m_Iterator;
90 ++m_Index;
91 return *this;
92 }
93
94 template<typename IT = I>
95 typename std::enable_if_t<std::is_copy_constructible_v<ipair_iterator<K, IT>>, ipair_iterator>
96 operator++(int) noexcept(std::is_nothrow_copy_constructible_v<ipair_iterator> && noexcept(++std::declval<K&>()) && noexcept(++std::declval<I&>()))
97 {
98 ipair_iterator iter = *this;
99 ++m_Iterator;
100 ++m_Index;
101 return iter;
102 }
103
104 template<typename IT = I>
105 typename std::enable_if_t<detail::is_decrementable_v<IT>, ipair_iterator&>
106 operator--() noexcept(noexcept(--std::declval<K&>()) && noexcept(--std::declval<I&>()))
107 {
108 --m_Iterator;
109 --m_Index;
110 return *this;
111 }
112
113 template<typename IT = I>
114 typename std::enable_if_t<std::is_copy_constructible_v<ipair_iterator<K, IT>> && detail::is_decrementable_v<IT>, ipair_iterator>
115 operator--(int) noexcept(std::is_nothrow_copy_constructible_v<ipair_iterator> && noexcept(--std::declval<K&>()) && noexcept(--std::declval<I&>()))
116 {
117 ipair_iterator iter = *this;
118 --m_Iterator;
119 --m_Index;
120 return iter;
121 }
122
123 bool operator==(const ipair_iterator& b) const noexcept(noexcept(std::declval<const I&>() == std::declval<const I&>()))
124 {
125 return m_Iterator == b.m_Iterator;
126 }
127
128 bool operator!=(const ipair_iterator& b) const noexcept(noexcept(std::declval<const I&>() != std::declval<const I&>()))
129 {
130 return m_Iterator != b.m_Iterator;
131 }
132
133 private:
134 KTL_EMPTY_BASE I m_Iterator;
135 KTL_EMPTY_BASE K m_Index;
136 };
137
138 template<typename K, typename C>
140 {
141 private:
142 static_assert(detail::is_iterable_v<C>, "Type must be iterable");
143
144 using begin_type = decltype(std::declval<C&>().begin());
145 using begin_const_type = decltype(std::declval<const C&>().begin());
146
147 public:
150
151 public:
152 template<typename V>
153 ipair_iterable(V&& container) noexcept(std::is_nothrow_constructible_v<C, V>) :
154 m_Container(std::forward<V>(container)) {}
155
156 template<typename V = C>
157 typename std::enable_if_t<detail::is_iterable_v<std::decay_t<V>>, iterator>
158 begin() noexcept(noexcept(std::declval<V&>().begin()) && noexcept(iterator(std::declval<begin_type>())))
159 {
160 return iterator(m_Container.begin());
161 }
162
163 template<typename V = C>
164 typename std::enable_if_t<detail::is_iterable_v<std::decay_t<V>>, iterator>
165 end() noexcept(noexcept(std::declval<V&>().end()) && noexcept(iterator(std::declval<begin_type>())))
166 {
167 return iterator(m_Container.end());
168 }
169
170 template<typename V = C>
171 typename std::enable_if_t<detail::is_iterable_v<std::add_const_t<std::decay_t<V>>>, const_iterator>
172 begin() const noexcept(noexcept(std::declval<const V&>().begin()) && noexcept(const_iterator(std::declval<begin_type>())))
173 {
174 return const_iterator(m_Container.begin());
175 }
176
177 template<typename V = C>
178 typename std::enable_if_t<detail::is_iterable_v<std::add_const_t<std::decay_t<V>>>, const_iterator>
179 end() const noexcept(noexcept(std::declval<const V&>().end()) && noexcept(const_iterator(std::declval<begin_type>())))
180 {
181 return const_iterator(m_Container.end());
182 }
183
184 private:
185 KTL_EMPTY_BASE C m_Container;
186 };
187
188 template<typename K, typename C>
189 ipair_iterable<K, C> ipair(C&& container) noexcept(std::is_nothrow_constructible_v<ipair_iterable<K, C>, C>)
190 {
191 return ipair_iterable<K, C>(std::forward<C>(container));
192 }
193
194 template<typename C>
195 ipair_iterable<size_t, C> ipair(C&& container) noexcept(std::is_nothrow_constructible_v<ipair_iterable<size_t, C>, C>)
196 {
197 return ipair<size_t, C>(std::forward<C>(container));
198 }
199}
Wraps an iterable object for use with indexed iterators.
Definition ipair.h:140
std::enable_if_t< detail::is_iterable_v< std::decay_t< V > >, iterator > end() noexcept(noexcept(std::declval< V & >().end()) &&noexcept(iterator(std::declval< begin_type >())))
Definition ipair.h:165
std::enable_if_t< detail::is_iterable_v< std::add_const_t< std::decay_t< V > > >, const_iterator > begin() const noexcept(noexcept(std::declval< const V & >().begin()) &&noexcept(const_iterator(std::declval< begin_type >())))
Definition ipair.h:172
ipair_iterable(V &&container) noexcept(std::is_nothrow_constructible_v< C, V >)
Definition ipair.h:153
ipair_iterator< K, begin_const_type > const_iterator
Definition ipair.h:149
std::enable_if_t< detail::is_iterable_v< std::decay_t< V > >, iterator > begin() noexcept(noexcept(std::declval< V & >().begin()) &&noexcept(iterator(std::declval< begin_type >())))
Definition ipair.h:158
ipair_iterator< K, begin_type > iterator
Definition ipair.h:148
std::enable_if_t< detail::is_iterable_v< std::add_const_t< std::decay_t< V > > >, const_iterator > end() const noexcept(noexcept(std::declval< const V & >().end()) &&noexcept(const_iterator(std::declval< begin_type >())))
Definition ipair.h:179
Wraps an iterator to return an index along with the value.
Definition ipair.h:61
ipair_iterator(I &&iterator) noexcept(std::is_nothrow_default_constructible_v< K > &&std::is_nothrow_move_constructible_v< I >)
Definition ipair.h:73
std::enable_if_t< std::is_copy_constructible_v< ipair_iterator< K, IT > >, ipair_iterator > operator++(int) noexcept(std::is_nothrow_copy_constructible_v< ipair_iterator > &&noexcept(++std::declval< K & >()) &&noexcept(++std::declval< I & >()))
Definition ipair.h:96
bool operator==(const ipair_iterator &b) const noexcept(noexcept(std::declval< const I & >()==std::declval< const I & >()))
Definition ipair.h:123
std::enable_if_t< std::is_copy_constructible_v< ipair_iterator< K, IT > > &&detail::is_decrementable_v< IT >, ipair_iterator > operator--(int) noexcept(std::is_nothrow_copy_constructible_v< ipair_iterator > &&noexcept(--std::declval< K & >()) &&noexcept(--std::declval< I & >()))
Definition ipair.h:115
value_type operator->() const noexcept(std::is_nothrow_constructible_v< value_type, K, I > &&noexcept(*std::declval< I & >()))
Definition ipair.h:82
ipair_iterator & operator++() noexcept(noexcept(++std::declval< K & >()) &&noexcept(++std::declval< I & >()))
Definition ipair.h:87
bool operator!=(const ipair_iterator &b) const noexcept(noexcept(std::declval< const I & >() !=std::declval< const I & >()))
Definition ipair.h:128
ipair_value< K, V > value_type
Definition ipair.h:68
std::enable_if_t< detail::is_decrementable_v< IT >, ipair_iterator & > operator--() noexcept(noexcept(--std::declval< K & >()) &&noexcept(--std::declval< I & >()))
Definition ipair.h:106
value_type operator*() const noexcept(std::is_nothrow_constructible_v< value_type, K, I > &&noexcept(*std::declval< I & >()))
Definition ipair.h:77
Pair of an index and value from an iterator.
Definition ipair.h:38
KTL_EMPTY_BASE K first
Definition ipair.h:55
ipair_value(A &&key, B &&value) noexcept(std::is_nothrow_constructible_v< K, A > &&std::is_nothrow_constructible_v< V, B >)
Definition ipair.h:41
const ipair_value * operator->() const noexcept
Definition ipair.h:50
KTL_EMPTY_BASE V second
Definition ipair.h:56
ipair_value * operator->() noexcept
Definition ipair.h:45
#define KTL_EMPTY_BASE
Definition empty_base.h:6
constexpr bool has_no_value_type_v
Definition meta.h:17
constexpr bool is_decrementable_v
Definition ipair.h:33
constexpr bool is_iterable_v
Definition ipair.h:23
Definition cascading.h:16
ipair_iterable< K, C > ipair(C &&container) noexcept(std::is_nothrow_constructible_v< ipair_iterable< K, C >, C >)
Wraps an iterable object to return an index along with the value.
Definition ipair.h:189
Definition ipair.h:27
Definition ipair.h:17