Loading...
Searching...
No Matches
vector_util.h
Go to the documentation of this file.
1#ifndef _BBM_VECTOR_UTIL_H_
2#define _BBM_VECTOR_UTIL_H_
3
4#include <vector>
5#include <ostream>
6#include <type_traits>
7
9
10#include "util/reference.h"
11#include "util/type_traits.h"
12#include "util/iterator_util.h"
13#include "util/multirange_for.h"
14
15/***********************************************************************/
16/*! \file vector_util.h
17 \brief Extensions for the STL vector class.
18************************************************************************/
19
20namespace bbm {
21
22 /*********************************************************************/
23 /*! @{ \name vector with support for references.
24 *********************************************************************/
25 template<typename T>
26 class vector : public std::vector<T>
27 {
28 using base_type = std::vector<T>;
29 public:
30 using value_type = typename base_type::value_type;
31 using allocator_type = typename base_type::allocator_type;
32 using size_type = typename base_type::size_type;
33 using difference_type = typename base_type::difference_type;
34 using reference = typename base_type::reference;
35 using const_reference = typename base_type::const_reference;
36 using pointer = typename base_type::pointer;
37 using const_pointer = typename base_type::const_pointer;
38 using iterator = typename base_type::iterator;
39 using const_iterator = typename base_type::const_iterator;
40 using reverse_iterator = typename base_type::reverse_iterator;
41 using const_reverse_iterator = typename base_type::const_reverse_iterator;
42
43 using base_type::base_type;
44 using base_type::operator=;
45 using base_type::operator[];
46
47 //! \brief Std vector Casting Constructor
48 template<typename... D>
49 vector(const std::vector<D...>& v) : base_type(v) {}
50
51 //! \brief Casting Constructor
52 template<typename U> requires concepts::assignable_to<U, T>
54 {
55 base_type::reserve(std::size(src));
56 for(auto& s : src) base_type::push_back(s);
57 }
58
59 //! \brief Casting Assignemnt
60 template<typename U> requires concepts::assignable_to<U, T>
62 {
63 vector temp(src);
64 std::swap(*this, temp);
65 return *this;
66 }
67
68 operator base_type() { return *this; }
69 operator base_type() const { return *this; }
70 };
71
72 /*********************************************************************/
73 /*! \brief vector<bbm::reference> with casting on the inspectors and iterators
74
75 The problem with vector<bbm::reference> is that the result of any
76 operation still needs to be manually cast when calling methods on
77 the result. This wrapper class will automatically do the casting.
78
79 If not a reference, bbm::vector will be equivalent to a std::vector
80 **********************************************************************/
81 template<typename T> requires std::is_reference_v<T>
82 class vector<T> : public std::vector< bbm::reference<T> >
83 {
84 using base_type = std::vector<bbm::reference<T> >;
85 public:
86 using value_type = typename base_type::value_type;
87 using allocator_type = typename base_type::allocator_type;
88 using size_type = typename base_type::size_type;
89 using difference_type = typename base_type::difference_type;
90 using reference = T;
92 using pointer = typename base_type::pointer;
93 using const_pointer = typename base_type::const_pointer;
95 using const_iterator = cast_itr<bbm::add_const_t<T>, typename base_type::const_iterator>;
97 using const_reverse_iterator = cast_itr<bbm::add_const_t<T>, typename base_type::const_reverse_iterator>;
98
99 using base_type::base_type;
100 using base_type::operator=;
101 using base_type::size;
102
103 //! \brief Casting Assignemnt
104 template<typename U> requires concepts::assignable_to<U, bbm::reference<T>>
106 {
107 if (std::size(src) != size()) throw bbm_size_error;
108 std::copy(std::begin(src), std::end(src), begin());
109 return *this;
110 }
111
112 //! @{ \name Auto-casting dereference methods
113 reference at(size_type idx) { return static_cast<reference>(base_type::at(idx)); }
114 const_reference at(size_type idx) const { return static_cast<const_reference>(base_type::at(idx)); }
115
116 reference operator[](size_type idx) { return static_cast<reference>(base_type::operator[](idx)); }
117 const_reference operator[](size_type idx) const { return static_cast<const_reference>(base_type::operator[](idx)); }
118
119 reference front(void) { return static_cast<reference>(base_type::front()); }
120 const_reference front(void) const { return static_cast<const_reference>(base_type::front()); }
121
122 reference back(void) { return static_cast<reference>(base_type::back()); }
123 const_reference back(void) const { return static_cast<const_reference>(base_type::back()); }
124 //! @}
125
126 //! @{ \name Auto-casting iterators
127 iterator begin(void) { return iterator(base_type::begin()); }
128 const_iterator begin(void) const { return const_iterator(base_type::begin()); }
129 iterator rbegin(void) { return iterator(base_type::rbegin()); }
130 const_iterator rbegin(void) const { return const_iterator(base_type::rbegin()); }
131 const_iterator cbegin(void) const { return const_iterator(base_type::cbegin()); }
132
133 iterator end(void) { return iterator(base_type::end()); }
134 const_iterator end(void) const { return const_iterator(base_type::end()); }
135 iterator rend(void) { return iterator(base_type::rend()); }
136 const_iterator rend(void) const { return const_iterator(base_type::rend()); }
137 const_iterator cend(void) const { return const_iterator(base_type::cend()); }
138 //! @}
139
140 //! \brief push_back reference encapsulation
141 template<typename R>
142 void push_back(R&& a) { base_type::push_back( bbm::reference<T>(std::forward<R>(a)) ); }
143
144 //! @{ \name Override insert to use emplace
145 constexpr iterator insert(const_iterator pos, value_type&& val) { return base_type::emplace(pos, std::forward<decltype(val)>(val)); }
146
147 constexpr iterator insert(const_iterator pos, size_t count, value_type&& val)
148 {
149 size_t idx = std::distance(cbegin(), pos);
150
151 // reserve memory
152 base_type::reserve(base_type::size() + count);
153
154 // compute emplace position
155 auto epos = std::next(base_type::begin(), idx);
156
157 // add
158 for(size_t c=0; c != count; ++c)
159 base_type::emplace(epos, std::forward<decltype(val)>(val));
160
161 // Done.
162 return std::prev(end(), count);
163 }
164
165 template<typename Itr>
166 constexpr iterator insert(const_iterator pos, Itr inputBegin, Itr inputEnd)
167 {
168 size_t idx = std::distance(cbegin(), pos);
169
170 // reserve memory
171 base_type::reserve(base_type::size() + std::distance(inputBegin, inputEnd));
172
173 // compute emplace position
174 auto epos = std::next(base_type::begin(), idx);
175
176 // add
177 for(auto itr = inputBegin; itr != inputEnd; ++itr)
178 {
179 // special case: cast_itr wrapping around a bbm_reference
180 if constexpr (is_bbm_reference_v<std::iter_value_t<underlying_itr_t<Itr>>>)
181 base_type::emplace(epos, itr.raw_dereference());
182
183 // regular iterator
184 else base_type::emplace(epos, *itr);
185 }
186
187 // Done.
188 return std::prev(end(), std::distance(inputBegin, inputEnd));
189 }
190 //! @}
191
192
193 };
194
195
196 /*** Implementation Details ***/
197 namespace detail {
198
199 template<typename T>
200 struct is_bbm_vector_impl : std::false_type {};
201
202 template<typename T>
203 struct is_bbm_vector_impl<bbm::vector<T>> : std::true_type {};
204 }
205
206 /*********************************************************************/
207 /*! @{ \name type traits for bbm::vector
208 *********************************************************************/
209 template<typename T>
210 using is_bbm_vector = bbm::detail::is_bbm_vector_impl<std::decay_t<T>>;
211
212 template<typename T>
214 //! @}
215
216
217 /*** Implementation details for mat operators ***/
218 namespace detail {
219
220 template<typename OP, typename T, typename U> requires ((is_vector_v<T> || is_bbm_vector_v<T>) && !(is_vector_v<U> || is_bbm_vector_v<U>))
221 inline auto vector_mathop(const T& vec, const U& u, const OP& op)
222 {
223 vector< decltype(vec[0] + u) > result; result.reserve( vec.size() );
224 for(auto& val : vec)
225 result.push_back( op(val, u) );
226 return result;
227 }
228
229 template<typename OP, typename T, typename U> requires ((is_vector_v<T> || is_bbm_vector_v<T>) && (is_vector_v<U> || is_bbm_vector_v<U>))
230 inline auto vector_mathop(const T& t, const U& u, const OP& op)
231 {
232 vector< decltype(t[0] + u[0]) > result; result.reserve( t.size() );
233 multirange_for([&](auto& t, auto& u) { result.push_back( op(t, u) ); }, t, u);
234 return result;
235 }
236
237 template<typename OP, typename T, typename U> requires ((is_vector_v<T> || is_bbm_vector_v<T>) && !(is_vector_v<U> || is_bbm_vector_v<U>) && !is_const_v<T>)
238 inline auto& vector_mathop_inplace(T& vec, const U& u, const OP& op)
239 {
240 for(auto& val : vec) op(val, u);
241 return vec;
242 }
243
244 template<typename OP, typename T, typename U> requires ((is_vector_v<T> || is_bbm_vector_v<T>) && (is_vector_v<U> || is_bbm_vector_v<U>) && !is_const_v<T>)
245 inline auto& vector_mathop_inplace(T& t, const U& u, const OP& op)
246 {
247 multirange_for(op, t, u);
248 return t;
249 }
250
251 }
252
253 /*********************************************************************/
254 /*! \@{ \name Math operators
255 *********************************************************************/
256
257 /*** Addition ***/
258 template<typename T, typename U> inline auto& operator+=(vector<T>& v, const U& u) { return bbm::detail::vector_mathop_inplace(v, u, [](auto& v, auto& u) { v += u; } ); }
259 template<typename T, typename U> inline auto operator+(const vector<T>& v, const U& u) { return bbm::detail::vector_mathop(v, u, [](auto& v, auto& u) { return (v + u); } ); }
260 template<typename T, typename U> requires (!is_vector_v<T> && !is_bbm_vector_v<T>) inline auto operator+(const T& v, const vector<U>& u) { return (u + v); }
261
262 /*** Subtraction ***/
263 template<typename T, typename U> inline auto& operator-=(vector<T>& v, const U& u) { return bbm::detail::vector_mathop_inplace(v, u, [](auto& v, auto& u) { v -= u; } ); }
264 template<typename T, typename U> inline auto operator-(const vector<T>& v, const U& u) { return bbm::detail::vector_mathop(v, u, [](auto& v, auto& u) { return (v - u); } ); }
265
266 /*** Multiplication ***/
267 template<typename T, typename U> inline auto& operator*=(vector<T>& v, const U& u) { return bbm::detail::vector_mathop_inplace(v, u, [](auto& v, auto& u) { v *= u; } ); }
268 template<typename T, typename U> inline auto operator*(const vector<T>& v, const U& u) { return bbm::detail::vector_mathop(v, u, [](auto& v, auto& u) { return (v * u); } ); }
269 template<typename T, typename U> requires (!is_vector_v<T> && !is_bbm_vector_v<T>) inline auto operator*(const T& v, const vector<U>& u) { return (u * v); }
270
271 /*** Division ***/
272 template<typename T, typename U> inline auto& operator/=(vector<T>& v, const U& u) { return bbm::detail::vector_mathop_inplace(v, u, [](auto& v, auto& u) { v /= u; } ); }
273 template<typename T, typename U> inline auto operator/(const vector<T>& v, const U& u) { return bbm::detail::vector_mathop(v, u, [](auto& v, auto& u) { return (v / u); } ); }
274
275 /*** Modulation ***/
276 template<typename T, typename U> inline auto& operator%=(vector<T>& v, const U& u) { return bbm::detail::vector_mathop_inplace(v, u, [](auto& v, auto& u) { v %= u; } ); }
277 template<typename T, typename U> inline auto operator%(const vector<T>& v, const U& u) { return bbm::detail::vector_mathop(v, u, [](auto& v, auto& u) { return (v % u); } ); }
278
279 //! @}
280
281
282 template<typename T>
283 std::ostream& operator<<(std::ostream& s, const std::vector<T>& vec)
284 {
285 s << bbm::toString(vec);
286 return s;
287 }
288
289} // end bbm namespace
290
291#endif /* _BBM_VECTOR_UTIL_H_ */
Cast iterator; cast the result after deferencing.
Definition: iterator_util.h:69
const_iterator cend(void) const
Definition: vector_util.h:137
typename base_type::pointer pointer
Definition: vector_util.h:92
const_iterator end(void) const
Definition: vector_util.h:134
constexpr iterator insert(const_iterator pos, size_t count, value_type &&val)
Definition: vector_util.h:147
iterator begin(void)
Definition: vector_util.h:127
bbm::add_const_t< T > const_reference
Definition: vector_util.h:91
std::vector< bbm::reference< T > > base_type
Definition: vector_util.h:84
iterator rbegin(void)
Definition: vector_util.h:129
const_reference back(void) const
Definition: vector_util.h:123
reference at(size_type idx)
Definition: vector_util.h:113
typename base_type::difference_type difference_type
Definition: vector_util.h:89
constexpr iterator insert(const_iterator pos, Itr inputBegin, Itr inputEnd)
Definition: vector_util.h:166
const_reference front(void) const
Definition: vector_util.h:120
reference operator[](size_type idx)
Definition: vector_util.h:116
const_iterator rend(void) const
Definition: vector_util.h:136
constexpr iterator insert(const_iterator pos, value_type &&val)
Definition: vector_util.h:145
iterator rend(void)
Definition: vector_util.h:135
const_reference operator[](size_type idx) const
Definition: vector_util.h:117
typename base_type::size_type size_type
Definition: vector_util.h:88
void push_back(R &&a)
push_back reference encapsulation
Definition: vector_util.h:142
const_iterator cbegin(void) const
Definition: vector_util.h:131
const_iterator begin(void) const
Definition: vector_util.h:128
const_iterator rbegin(void) const
Definition: vector_util.h:130
reference front(void)
Definition: vector_util.h:119
T reference
Definition: vector_util.h:90
reference back(void)
Definition: vector_util.h:122
iterator end(void)
Definition: vector_util.h:133
const_reference at(size_type idx) const
Definition: vector_util.h:114
typename base_type::const_pointer const_pointer
Definition: vector_util.h:93
typename base_type::value_type value_type
Definition: vector_util.h:86
bbm::vector< T > & operator=(const bbm::vector< U > &src)
Casting Assignemnt.
Definition: vector_util.h:105
typename base_type::allocator_type allocator_type
Definition: vector_util.h:87
Definition: vector_util.h:27
typename base_type::pointer pointer
Definition: vector_util.h:36
typename base_type::difference_type difference_type
Definition: vector_util.h:33
typename base_type::iterator iterator
Definition: vector_util.h:38
typename base_type::const_iterator const_iterator
Definition: vector_util.h:39
bbm::vector< T > & operator=(const bbm::vector< U > &src)
Casting Assignemnt.
Definition: vector_util.h:61
typename base_type::size_type size_type
Definition: vector_util.h:32
typename base_type::const_reference const_reference
Definition: vector_util.h:35
typename base_type::const_reverse_iterator const_reverse_iterator
Definition: vector_util.h:41
typename base_type::reverse_iterator reverse_iterator
Definition: vector_util.h:40
std::vector< T > base_type
Definition: vector_util.h:28
typename base_type::reference reference
Definition: vector_util.h:34
vector(const std::vector< D... > &v)
Std vector Casting Constructor.
Definition: vector_util.h:49
typename base_type::const_pointer const_pointer
Definition: vector_util.h:37
typename base_type::value_type value_type
Definition: vector_util.h:30
typename base_type::allocator_type allocator_type
Definition: vector_util.h:31
vector(const bbm::vector< U > &src)
Casting Constructor.
Definition: vector_util.h:53
assignable_to: reverse of std::assignable_from
Definition: util.h:43
#define bbm_size_error
Definition: error.h:45
concept to check if a type has a valid string_converter.
Extensions for STL iterators/ranges.
ranged for loop over multiple containers at once
Definition: aggregatebsdf.h:29
auto operator/(const vector< T > &v, const U &u)
Definition: vector_util.h:273
constexpr FLAGNAME operator+(FLAGNAME a, FLAGNAME b)
Conact two flags.
Definition: flags.h:40
constexpr FLAGNAME & operator+=(FLAGNAME &a, FLAGNAME b)
Update 'a' with a+b.
Definition: flags.h:84
auto & operator*=(vector< T > &v, const U &u)
Definition: vector_util.h:267
auto operator*(const vector< T > &v, const U &u)
Definition: vector_util.h:268
auto & operator/=(vector< T > &v, const U &u)
Definition: vector_util.h:272
void multirange_for(FUNC &&func, Ts &&... containers)
ranged for loop over multiple containers at once
Definition: multirange_for.h:43
auto & operator%=(vector< T > &v, const U &u)
Definition: vector_util.h:276
std::ostream & operator<<(std::ostream &s, const BSDF &bsdf)
Definition: bsdf_base.h:138
auto end(T &&t)
Definition: iterator_util.h:43
size_t size(T &&t)
Definition: iterator_util.h:22
bbm::detail::is_bbm_vector_impl< std::decay_t< T > > is_bbm_vector
Definition: vector_util.h:210
std::string toString(const T &)
toString alias
Definition: stringconvert.h:594
typename add_const< T >::type add_const_t
Definition: type_traits.h:42
constexpr bool is_bbm_vector_v
Definition: vector_util.h:213
auto operator%(const vector< T > &v, const U &u)
Definition: vector_util.h:277
auto begin(T &&t)
Definition: iterator_util.h:29
auto & operator-=(vector< T > &v, const U &u)
Definition: vector_util.h:263
auto operator-(const vector< T > &v, const U &u)
Definition: vector_util.h:264
auto cbegin(T &&t)
Definition: iterator_util.h:36
Assignable reference with wrapper support for rvalues.
Non-persistent reference (i.e., cannot take rvalues)
Definition: reference.h:86