1 /*************************************************************************** 2 * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 * Copyright (c) QuantStack * 4 * * 5 * Distributed under the terms of the BSD 3-Clause License. * 6 * * 7 * The full license is in the file LICENSE, distributed with this software. * 8 ****************************************************************************/ 9 10 #ifndef XOPTIONAL_ASSEMBLY_STORAGE_HPP 11 #define XOPTIONAL_ASSEMBLY_STORAGE_HPP 12 13 #include "xtl/xiterator_base.hpp" 14 15 #include "xoptional.hpp" 16 #include "xsemantic.hpp" 17 18 namespace xt 19 { 20 template <class VE, class FE, bool is_const> 21 class xoptional_assembly_storage_iterator; 22 23 /****************************** 24 * xoptional_assembly_storage * 25 ******************************/ 26 27 template <class VE, class FE> 28 class xoptional_assembly_storage 29 { 30 public: 31 32 using self_type = xoptional_assembly_storage<VE, FE>; 33 34 using value_storage = std::remove_reference_t<VE>; 35 using flag_storage = std::remove_reference_t<FE>; 36 37 using value_type = xtl::xoptional<typename value_storage::value_type, typename flag_storage::value_type>; 38 39 static constexpr bool is_val_const = std::is_const<value_storage>::value; 40 static constexpr bool is_flag_const = std::is_const<flag_storage>::value; 41 using val_reference = std::conditional_t<is_val_const, 42 typename value_storage::const_reference, 43 typename value_storage::reference>; 44 using flag_reference = std::conditional_t<is_flag_const, 45 typename flag_storage::const_reference, 46 typename flag_storage::reference>; 47 using reference = xtl::xoptional<val_reference, flag_reference>; 48 using const_reference = xtl::xoptional<typename value_storage::const_reference, typename flag_storage::const_reference>; 49 50 using pointer = xtl::xclosure_pointer<reference>; 51 using const_pointer = xtl::xclosure_pointer<const_reference>; 52 53 using size_type = typename value_storage::size_type; 54 using difference_type = typename value_storage::difference_type; 55 56 using iterator = xoptional_assembly_storage_iterator<VE, FE, false>; 57 using const_iterator = xoptional_assembly_storage_iterator<VE, FE, true>; 58 using reverse_iterator = std::reverse_iterator<iterator>; 59 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 60 61 template <class VE1, class FE1> 62 xoptional_assembly_storage(const VE1& value_stor, const FE1& flag_stor); 63 64 template <class VE1, class FE1> 65 xoptional_assembly_storage(VE1& value_stor, FE1& flag_stor); 66 67 xoptional_assembly_storage(const xoptional_assembly_storage&); 68 xoptional_assembly_storage& operator=(const xoptional_assembly_storage&); 69 xoptional_assembly_storage(xoptional_assembly_storage&&); 70 xoptional_assembly_storage& operator=(xoptional_assembly_storage&&); 71 72 bool empty() const noexcept; 73 size_type size() const noexcept; 74 void resize(size_type size); 75 76 reference operator[](size_type i); 77 const_reference operator[](size_type i) const; 78 79 reference front(); 80 const_reference front() const; 81 82 reference back(); 83 const_reference back() const; 84 85 pointer data() noexcept; 86 const_pointer data() const noexcept; 87 88 iterator begin() noexcept; 89 iterator end() noexcept; 90 91 const_iterator begin() const noexcept; 92 const_iterator end() const noexcept; 93 94 const_iterator cbegin() const noexcept; 95 const_iterator cend() const noexcept; 96 97 reverse_iterator rbegin() noexcept; 98 reverse_iterator rend() noexcept; 99 100 const_reverse_iterator rbegin() const noexcept; 101 const_reverse_iterator rend() const noexcept; 102 103 const_reverse_iterator crbegin() const noexcept; 104 const_reverse_iterator crend() const noexcept; 105 106 void swap(self_type& rhs) noexcept; 107 108 value_storage& value() noexcept; 109 const value_storage& value() const noexcept; 110 111 flag_storage& has_value() noexcept; 112 const flag_storage& has_value() const noexcept; 113 114 private: 115 116 VE m_value; 117 FE m_has_value; 118 }; 119 120 template <class VE, class FE> 121 bool operator==(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs); 122 123 template <class VE, class FE> 124 bool operator!=(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs); 125 126 template <class VE, class FE> 127 bool operator<(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs); 128 129 template <class VE, class FE> 130 bool operator<=(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs); 131 132 template <class VE, class FE> 133 bool operator>(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs); 134 135 template <class VE, class FE> 136 bool operator>=(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs); 137 138 template <class VE, class FE> 139 void swap(xoptional_assembly_storage<VE, FE>& lhs, xoptional_assembly_storage<VE, FE>& rhs) noexcept; 140 141 /*************************************** 142 * xoptional_assembly_storage_iterator * 143 ***************************************/ 144 145 template <class VE, class FE, bool is_const> 146 class xoptional_assembly_storage_iterator; 147 148 template <class VE, class FE, bool is_const> 149 struct xoptional_assembly_storage_iterator_traits 150 { 151 using iterator_type = xoptional_assembly_storage_iterator<VE, FE, is_const>; 152 using xoptional_assembly_storage_type = xoptional_assembly_storage<VE, FE>; 153 using value_type = typename xoptional_assembly_storage_type::value_type; 154 using reference = std::conditional_t<is_const, 155 typename xoptional_assembly_storage_type::const_reference, 156 typename xoptional_assembly_storage_type::reference>; 157 using difference_type = typename xoptional_assembly_storage_type::difference_type; 158 using pointer = std::conditional_t<is_const, 159 typename xoptional_assembly_storage_type::const_pointer, 160 typename xoptional_assembly_storage_type::pointer>; 161 }; 162 163 template <class VE, class FE, bool is_const> 164 class xoptional_assembly_storage_iterator 165 : public xtl::xrandom_access_iterator_base2<xoptional_assembly_storage_iterator_traits<VE, FE, is_const>> 166 { 167 public: 168 169 using self_type = xoptional_assembly_storage_iterator<VE, FE, is_const>; 170 using base_type = xtl::xrandom_access_iterator_base2<xoptional_assembly_storage_iterator_traits<VE, FE, is_const>>; 171 172 using xoptional_assembly_storage_type = xoptional_assembly_storage<VE, FE>; 173 using value_iterator = std::conditional_t<is_const, 174 typename xoptional_assembly_storage_type::value_storage::const_iterator, 175 typename xoptional_assembly_storage_type::value_storage::iterator>; 176 using flag_iterator = std::conditional_t<is_const, 177 typename xoptional_assembly_storage_type::flag_storage::const_iterator, 178 typename xoptional_assembly_storage_type::flag_storage::iterator>; 179 180 using value_type = typename base_type::value_type; 181 using reference = typename base_type::reference; 182 using pointer = typename base_type::pointer; 183 using difference_type = typename base_type::difference_type; 184 185 xoptional_assembly_storage_iterator(value_iterator value_it, flag_iterator flag_it); 186 187 self_type& operator++(); 188 self_type& operator--(); 189 190 self_type& operator+=(difference_type n); 191 self_type& operator-=(difference_type n); 192 193 difference_type operator-(const self_type& rhs) const; 194 195 reference operator*() const; 196 pointer operator->() const; 197 198 bool operator==(const self_type& rhs) const; 199 bool operator<(const self_type& rhs) const; 200 201 private: 202 203 value_iterator m_value_it; 204 flag_iterator m_flag_it; 205 }; 206 207 /********************************************* 208 * xoptional_assembly_storage implementation * 209 *********************************************/ 210 211 template <class VE, class FE> 212 template <class VE1, class FE1> xoptional_assembly_storage(const VE1 & value_stor,const FE1 & flag_stor)213 inline xoptional_assembly_storage<VE, FE>::xoptional_assembly_storage(const VE1& value_stor, const FE1& flag_stor) 214 : m_value(value_stor), m_has_value(flag_stor) 215 { 216 } 217 218 template <class VE, class FE> 219 template <class VE1, class FE1> xoptional_assembly_storage(VE1 & value_stor,FE1 & flag_stor)220 inline xoptional_assembly_storage<VE, FE>::xoptional_assembly_storage(VE1& value_stor, FE1& flag_stor) 221 : m_value(value_stor), m_has_value(flag_stor) 222 { 223 } 224 225 template <class VE, class FE> xoptional_assembly_storage(const self_type & rhs)226 inline xoptional_assembly_storage<VE, FE>::xoptional_assembly_storage(const self_type& rhs) 227 : m_value(rhs.m_value), m_has_value(rhs.m_has_value) 228 { 229 } 230 231 template <class VE, class FE> operator =(const self_type & rhs)232 inline auto xoptional_assembly_storage<VE, FE>::operator=(const self_type& rhs) -> self_type& 233 { 234 m_value = rhs.m_value; 235 m_has_value = rhs.m_has_value; 236 return *this; 237 } 238 239 template <class VE, class FE> xoptional_assembly_storage(self_type && rhs)240 inline xoptional_assembly_storage<VE, FE>::xoptional_assembly_storage(self_type&& rhs) 241 : m_value(std::forward<VE>(rhs.m_value)), m_has_value(std::forward<FE>(rhs.m_has_value)) 242 { 243 } 244 245 template <class VE, class FE> operator =(self_type && rhs)246 inline auto xoptional_assembly_storage<VE, FE>::operator=(self_type&& rhs) -> self_type& 247 { 248 m_value = std::forward<VE>(rhs.m_value); 249 m_has_value = std::forward<FE>(rhs.m_has_value); 250 return *this; 251 } 252 253 template <class VE, class FE> empty() const254 inline bool xoptional_assembly_storage<VE, FE>::empty() const noexcept 255 { 256 return value().empty(); 257 } 258 259 template <class VE, class FE> size() const260 inline auto xoptional_assembly_storage<VE, FE>::size() const noexcept -> size_type 261 { 262 return value().size(); 263 } 264 265 template <class VE, class FE> resize(size_type size)266 inline void xoptional_assembly_storage<VE, FE>::resize(size_type size) 267 { 268 value().resize(size); 269 has_value().resize(size); 270 } 271 272 template <class VE, class FE> operator [](size_type i)273 inline auto xoptional_assembly_storage<VE, FE>::operator[](size_type i) -> reference 274 { 275 return reference(value()[i], has_value()[i]); 276 } 277 278 template <class VE, class FE> operator [](size_type i) const279 inline auto xoptional_assembly_storage<VE, FE>::operator[](size_type i) const -> const_reference 280 { 281 return const_reference(value()[i], has_value()[i]); 282 } 283 284 template <class VE, class FE> front()285 inline auto xoptional_assembly_storage<VE, FE>::front() -> reference 286 { 287 return reference(value()[0], has_value()[0]); 288 } 289 290 template <class VE, class FE> front() const291 inline auto xoptional_assembly_storage<VE, FE>::front() const -> const_reference 292 { 293 return const_reference(value()[0], has_value()[0]); 294 } 295 296 template <class VE, class FE> back()297 inline auto xoptional_assembly_storage<VE, FE>::back() -> reference 298 { 299 return reference(value()[size() - 1], has_value()[size() - 1]); 300 } 301 302 template <class VE, class FE> back() const303 inline auto xoptional_assembly_storage<VE, FE>::back() const -> const_reference 304 { 305 return const_reference(value()[size() - 1], has_value()[size() - 1]); 306 } 307 308 template <class VE, class FE> data()309 inline auto xoptional_assembly_storage<VE, FE>::data() noexcept -> pointer 310 { 311 pointer(front()); 312 } 313 314 template <class VE, class FE> data() const315 inline auto xoptional_assembly_storage<VE, FE>::data() const noexcept -> const_pointer 316 { 317 const_pointer(front()); 318 } 319 320 template <class VE, class FE> begin()321 inline auto xoptional_assembly_storage<VE, FE>::begin() noexcept -> iterator 322 { 323 return iterator(value().begin(), has_value().begin()); 324 } 325 326 template <class VE, class FE> end()327 inline auto xoptional_assembly_storage<VE, FE>::end() noexcept -> iterator 328 { 329 return iterator(value().end(), has_value().end()); 330 } 331 332 template <class VE, class FE> begin() const333 inline auto xoptional_assembly_storage<VE, FE>::begin() const noexcept -> const_iterator 334 { 335 return cbegin(); 336 } 337 338 template <class VE, class FE> end() const339 inline auto xoptional_assembly_storage<VE, FE>::end() const noexcept -> const_iterator 340 { 341 return cend(); 342 } 343 344 template <class VE, class FE> cbegin() const345 inline auto xoptional_assembly_storage<VE, FE>::cbegin() const noexcept -> const_iterator 346 { 347 return const_iterator(value().begin(), has_value().begin()); 348 } 349 350 template <class VE, class FE> cend() const351 inline auto xoptional_assembly_storage<VE, FE>::cend() const noexcept -> const_iterator 352 { 353 return const_iterator(value().end(), has_value().end()); 354 } 355 356 template <class VE, class FE> rbegin()357 inline auto xoptional_assembly_storage<VE, FE>::rbegin() noexcept -> reverse_iterator 358 { 359 return reverse_iterator(end()); 360 } 361 362 template <class VE, class FE> rend()363 inline auto xoptional_assembly_storage<VE, FE>::rend() noexcept -> reverse_iterator 364 { 365 return reverse_iterator(begin()); 366 } 367 368 template <class VE, class FE> rbegin() const369 inline auto xoptional_assembly_storage<VE, FE>::rbegin() const noexcept -> const_reverse_iterator 370 { 371 return crbegin(); 372 } 373 374 template <class VE, class FE> rend() const375 inline auto xoptional_assembly_storage<VE, FE>::rend() const noexcept -> const_reverse_iterator 376 { 377 return crend(); 378 } 379 380 template <class VE, class FE> crbegin() const381 inline auto xoptional_assembly_storage<VE, FE>::crbegin() const noexcept -> const_reverse_iterator 382 { 383 return const_reverse_iterator(cend()); 384 } 385 386 template <class VE, class FE> crend() const387 inline auto xoptional_assembly_storage<VE, FE>::crend() const noexcept -> const_reverse_iterator 388 { 389 return const_reverse_iterator(cbegin()); 390 } 391 392 template <class VE, class FE> swap(self_type & rhs)393 inline void xoptional_assembly_storage<VE, FE>::swap(self_type& rhs) noexcept 394 { 395 m_value.swap(rhs.m_value); 396 m_has_value.swap(rhs.m_has_value); 397 } 398 399 template <class VE, class FE> value()400 inline auto xoptional_assembly_storage<VE, FE>::value() noexcept -> value_storage& 401 { 402 return m_value; 403 } 404 405 template <class VE, class FE> value() const406 inline auto xoptional_assembly_storage<VE, FE>::value() const noexcept -> const value_storage& 407 { 408 return m_value; 409 } 410 411 template <class VE, class FE> has_value()412 inline auto xoptional_assembly_storage<VE, FE>::has_value() noexcept -> flag_storage& 413 { 414 return m_has_value; 415 } 416 417 template <class VE, class FE> has_value() const418 inline auto xoptional_assembly_storage<VE, FE>::has_value() const noexcept -> const flag_storage& 419 { 420 return m_has_value; 421 } 422 423 template <class VE, class FE> operator ==(const xoptional_assembly_storage<VE,FE> & lhs,const xoptional_assembly_storage<VE,FE> & rhs)424 bool operator==(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs) 425 { 426 return lhs.value() == rhs.value() && lhs.has_value() == rhs.has_value(); 427 } 428 429 template <class VE, class FE> operator !=(const xoptional_assembly_storage<VE,FE> & lhs,const xoptional_assembly_storage<VE,FE> & rhs)430 bool operator!=(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs) 431 { 432 return !(lhs == rhs); 433 } 434 435 template <class VE, class FE> operator <(const xoptional_assembly_storage<VE,FE> & lhs,const xoptional_assembly_storage<VE,FE> & rhs)436 bool operator<(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs) 437 { 438 return lhs.value() < rhs.value() && lhs.has_value() == rhs.has_value(); 439 } 440 441 template <class VE, class FE> operator <=(const xoptional_assembly_storage<VE,FE> & lhs,const xoptional_assembly_storage<VE,FE> & rhs)442 bool operator<=(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs) 443 { 444 return lhs.value() <= rhs.value() && lhs.has_value() == rhs.has_value(); 445 } 446 447 template <class VE, class FE> operator >(const xoptional_assembly_storage<VE,FE> & lhs,const xoptional_assembly_storage<VE,FE> & rhs)448 bool operator>(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs) 449 { 450 return lhs.value() > rhs.value() && lhs.has_value() == rhs.has_value(); 451 } 452 453 template <class VE, class FE> operator >=(const xoptional_assembly_storage<VE,FE> & lhs,const xoptional_assembly_storage<VE,FE> & rhs)454 bool operator>=(const xoptional_assembly_storage<VE, FE>& lhs, const xoptional_assembly_storage<VE, FE>& rhs) 455 { 456 return lhs.value() >= rhs.value() && lhs.has_value() == rhs.has_value(); 457 } 458 459 template <class VE, class FE> swap(xoptional_assembly_storage<VE,FE> & lhs,xoptional_assembly_storage<VE,FE> & rhs)460 void swap(xoptional_assembly_storage<VE, FE>& lhs, xoptional_assembly_storage<VE, FE>& rhs) noexcept 461 { 462 lhs.swap(rhs); 463 } 464 465 /****************************************************** 466 * xoptional_assembly_storage_iterator implementation * 467 ******************************************************/ 468 469 template <class VE, class FE, bool C> xoptional_assembly_storage_iterator(value_iterator value_it,flag_iterator flag_it)470 inline xoptional_assembly_storage_iterator<VE, FE, C>::xoptional_assembly_storage_iterator(value_iterator value_it, flag_iterator flag_it) 471 : m_value_it(value_it), m_flag_it(flag_it) 472 { 473 } 474 475 template <class VE, class FE, bool C> operator ++()476 inline auto xoptional_assembly_storage_iterator<VE, FE, C>::operator++() -> self_type& 477 { 478 ++m_value_it; 479 ++m_flag_it; 480 return *this; 481 } 482 483 template <class VE, class FE, bool C> operator --()484 inline auto xoptional_assembly_storage_iterator<VE, FE, C>::operator--() -> self_type& 485 { 486 --m_value_it; 487 --m_flag_it; 488 return *this; 489 } 490 491 template <class VE, class FE, bool C> operator +=(difference_type n)492 inline auto xoptional_assembly_storage_iterator<VE, FE, C>::operator+=(difference_type n) -> self_type& 493 { 494 m_value_it += n; 495 m_flag_it += n; 496 return *this; 497 } 498 499 template <class VE, class FE, bool C> operator -=(difference_type n)500 inline auto xoptional_assembly_storage_iterator<VE, FE, C>::operator-=(difference_type n) -> self_type& 501 { 502 m_value_it -= n; 503 m_flag_it -= n; 504 return *this; 505 } 506 507 template <class VE, class FE, bool C> operator -(const self_type & rhs) const508 inline auto xoptional_assembly_storage_iterator<VE, FE, C>::operator-(const self_type& rhs) const -> difference_type 509 { 510 return m_value_it - rhs.m_value_it; 511 } 512 513 template <class VE, class FE, bool C> operator *() const514 inline auto xoptional_assembly_storage_iterator<VE, FE, C>::operator*() const -> reference 515 { 516 return reference(*m_value_it, *m_flag_it); 517 } 518 519 template <class VE, class FE, bool C> operator ->() const520 inline auto xoptional_assembly_storage_iterator<VE, FE, C>::operator->() const -> pointer 521 { 522 return &(this->operator*()); 523 } 524 525 template <class VE, class FE, bool C> operator ==(const self_type & rhs) const526 inline bool xoptional_assembly_storage_iterator<VE, FE, C>::operator==(const self_type& rhs) const 527 { 528 return m_value_it == rhs.m_value_it; 529 } 530 531 template <class VE, class FE, bool C> operator <(const self_type & rhs) const532 inline bool xoptional_assembly_storage_iterator<VE, FE, C>::operator<(const self_type& rhs) const 533 { 534 return m_value_it < rhs.m_value_it; 535 } 536 537 template <class VE, class FE> optional_assembly_storage(const VE & value,const FE & flag)538 inline xoptional_assembly_storage<VE, FE> optional_assembly_storage(const VE& value, const FE& flag) 539 { 540 return xoptional_assembly_storage<VE, FE>(value, flag); 541 } 542 543 template <class VE, class FE> optional_assembly_storage(VE & value,FE & flag)544 inline xoptional_assembly_storage<VE, FE> optional_assembly_storage(VE& value, FE& flag) 545 { 546 return xoptional_assembly_storage<VE, FE>(value, flag); 547 } 548 } 549 550 #endif 551