xoptional_sequence.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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. #ifndef XTL_OPTIONAL_SEQUENCE_HPP
  10. #define XTL_OPTIONAL_SEQUENCE_HPP
  11. #include <array>
  12. #include <bitset>
  13. #include <cstddef>
  14. #include <iterator>
  15. #include <memory>
  16. #include <utility>
  17. #include <vector>
  18. #include "xdynamic_bitset.hpp"
  19. #include "xiterator_base.hpp"
  20. #include "xoptional.hpp"
  21. #include "xsequence.hpp"
  22. namespace xtl
  23. {
  24. /**************************************
  25. * Optimized 1-D xoptional containers *
  26. **************************************/
  27. template <class ITV, class ITB>
  28. class xoptional_iterator;
  29. template <class BC, class FC>
  30. class xoptional_sequence
  31. {
  32. public:
  33. // Internal typedefs
  34. using base_container_type = BC;
  35. using base_value_type = typename base_container_type::value_type;
  36. using base_reference = typename base_container_type::reference;
  37. using base_const_reference = typename base_container_type::const_reference;
  38. using flag_container_type = FC;
  39. using flag_type = typename flag_container_type::value_type;
  40. using flag_reference = typename flag_container_type::reference;
  41. using flag_const_reference = typename flag_container_type::const_reference;
  42. // Container typedefs
  43. using value_type = xoptional<base_value_type, flag_type>;
  44. using reference = xoptional<base_reference, flag_reference>;
  45. using const_reference = xoptional<base_const_reference, flag_const_reference>;
  46. using pointer = xclosure_pointer<reference>;
  47. using const_pointer = xclosure_pointer<const_reference>;
  48. // Other typedefs
  49. using size_type = typename base_container_type::size_type;
  50. using difference_type = typename base_container_type::difference_type;
  51. using iterator = xoptional_iterator<typename base_container_type::iterator,
  52. typename flag_container_type::iterator>;
  53. using const_iterator = xoptional_iterator<typename base_container_type::const_iterator,
  54. typename flag_container_type::const_iterator>;
  55. using reverse_iterator = xoptional_iterator<typename base_container_type::reverse_iterator,
  56. typename flag_container_type::reverse_iterator>;
  57. using const_reverse_iterator = xoptional_iterator<typename base_container_type::const_reverse_iterator,
  58. typename flag_container_type::const_reverse_iterator>;
  59. bool empty() const noexcept;
  60. size_type size() const noexcept;
  61. size_type max_size() const noexcept;
  62. reference at(size_type i);
  63. const_reference at(size_type i) const;
  64. reference operator[](size_type i);
  65. const_reference operator[](size_type i) const;
  66. reference front();
  67. const_reference front() const;
  68. reference back();
  69. const_reference back() const;
  70. iterator begin() noexcept;
  71. iterator end() noexcept;
  72. const_iterator begin() const noexcept;
  73. const_iterator end() const noexcept;
  74. const_iterator cbegin() const noexcept;
  75. const_iterator cend() const noexcept;
  76. reverse_iterator rbegin() noexcept;
  77. reverse_iterator rend() noexcept;
  78. const_reverse_iterator rbegin() const noexcept;
  79. const_reverse_iterator rend() const noexcept;
  80. const_reverse_iterator crbegin() const noexcept;
  81. const_reverse_iterator crend() const noexcept;
  82. base_container_type value() && noexcept;
  83. base_container_type& value() & noexcept;
  84. const base_container_type& value() const & noexcept;
  85. flag_container_type has_value() && noexcept;
  86. flag_container_type& has_value() & noexcept;
  87. const flag_container_type& has_value() const & noexcept;
  88. protected:
  89. xoptional_sequence() = default;
  90. xoptional_sequence(size_type s, const base_value_type& v);
  91. template <class CTO, class CBO>
  92. xoptional_sequence(size_type s, const xoptional<CTO, CBO>& v);
  93. ~xoptional_sequence() = default;
  94. xoptional_sequence(const xoptional_sequence&) = default;
  95. xoptional_sequence& operator=(const xoptional_sequence&) = default;
  96. xoptional_sequence(xoptional_sequence&&) = default;
  97. xoptional_sequence& operator=(xoptional_sequence&&) = default;
  98. base_container_type m_values;
  99. flag_container_type m_flags;
  100. };
  101. template <class BC, class FC>
  102. bool operator==(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
  103. template <class BC, class FC>
  104. bool operator!=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
  105. template <class BC, class FC>
  106. bool operator<(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
  107. template <class BC, class FC>
  108. bool operator<=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
  109. template <class BC, class FC>
  110. bool operator>(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
  111. template <class BC, class FC>
  112. bool operator>=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
  113. /********************************
  114. * xoptional_array declarations *
  115. ********************************/
  116. // There is no value_type in std::bitset ...
  117. template <class T, std::size_t I, class BC = xdynamic_bitset<std::size_t>>
  118. class xoptional_array : public xoptional_sequence<std::array<T, I>, BC>
  119. {
  120. public:
  121. using self_type = xoptional_array;
  122. using base_container_type = std::array<T, I>;
  123. using flag_container_type = BC;
  124. using base_type = xoptional_sequence<base_container_type, flag_container_type>;
  125. using base_value_type = typename base_type::base_value_type;
  126. using size_type = typename base_type::size_type;
  127. xoptional_array() = default;
  128. xoptional_array(size_type s, const base_value_type& v);
  129. template <class CTO, class CBO>
  130. xoptional_array(size_type s, const xoptional<CTO, CBO>& v);
  131. };
  132. /********************
  133. * xoptional_vector *
  134. ********************/
  135. template <class T, class A = std::allocator<T>, class BC = xdynamic_bitset<std::size_t>>
  136. class xoptional_vector : public xoptional_sequence<std::vector<T, A>, BC>
  137. {
  138. public:
  139. using self_type = xoptional_vector;
  140. using base_container_type = std::vector<T, A>;
  141. using flag_container_type = BC;
  142. using base_type = xoptional_sequence<base_container_type, flag_container_type>;
  143. using base_value_type = typename base_type::base_value_type;
  144. using allocator_type = A;
  145. using value_type = typename base_type::value_type;
  146. using size_type = typename base_type::size_type;
  147. using difference_type = typename base_type::difference_type;
  148. using reference = typename base_type::reference;
  149. using const_reference = typename base_type::const_reference;
  150. using pointer = typename base_type::pointer;
  151. using const_pointer = typename base_type::const_pointer;
  152. using iterator = typename base_type::iterator;
  153. using const_iterator = typename base_type::const_iterator;
  154. using reverse_iterator = typename base_type::reverse_iterator;
  155. using const_reverse_iterator = typename base_type::const_reverse_iterator;
  156. xoptional_vector() = default;
  157. xoptional_vector(size_type, const base_value_type&);
  158. template <class CTO, class CBO>
  159. xoptional_vector(size_type, const xoptional<CTO, CBO>&);
  160. void resize(size_type);
  161. void resize(size_type, const base_value_type&);
  162. template <class CTO, class CBO>
  163. void resize(size_type, const xoptional<CTO, CBO>&);
  164. };
  165. /**********************************
  166. * xoptional_iterator declaration *
  167. **********************************/
  168. template <class ITV, class ITB>
  169. struct xoptional_iterator_traits
  170. {
  171. using iterator_type = xoptional_iterator<ITV, ITB>;
  172. using value_type = xoptional<typename ITV::value_type, typename ITB::value_type>;
  173. using reference = xoptional<typename ITV::reference, typename ITB::reference>;
  174. using pointer = xclosure_pointer<reference>;
  175. using difference_type = typename ITV::difference_type;
  176. };
  177. template <class ITV, class ITB>
  178. class xoptional_iterator : public xrandom_access_iterator_base2<xoptional_iterator_traits<ITV, ITB>>
  179. {
  180. public:
  181. using self_type = xoptional_iterator<ITV, ITB>;
  182. using base_type = xrandom_access_iterator_base2<xoptional_iterator_traits<ITV, ITB>>;
  183. using value_type = typename base_type::value_type;
  184. using reference = typename base_type::reference;
  185. using pointer = typename base_type::pointer;
  186. using difference_type = typename base_type::difference_type;
  187. xoptional_iterator() = default;
  188. xoptional_iterator(ITV itv, ITB itb);
  189. self_type& operator++();
  190. self_type& operator--();
  191. self_type& operator+=(difference_type n);
  192. self_type& operator-=(difference_type n);
  193. difference_type operator-(const self_type& rhs) const;
  194. reference operator*() const;
  195. pointer operator->() const;
  196. bool operator==(const self_type& rhs) const;
  197. bool operator<(const self_type& rhs) const;
  198. private:
  199. ITV m_itv;
  200. ITB m_itb;
  201. };
  202. /*************************************
  203. * xoptional_sequence implementation *
  204. *************************************/
  205. template <class BC, class FC>
  206. inline xoptional_sequence<BC, FC>::xoptional_sequence(size_type s, const base_value_type& v)
  207. : m_values(make_sequence<base_container_type>(s, v)),
  208. m_flags(make_sequence<flag_container_type>(s, true))
  209. {
  210. }
  211. template <class BC, class FC>
  212. template <class CTO, class CBO>
  213. inline xoptional_sequence<BC, FC>::xoptional_sequence(size_type s, const xoptional<CTO, CBO>& v)
  214. : m_values(make_sequence<base_container_type>(s, v.value())), m_flags(make_sequence<flag_container_type>(s, v.has_value()))
  215. {
  216. }
  217. template <class BC, class FC>
  218. inline auto xoptional_sequence<BC, FC>::empty() const noexcept -> bool
  219. {
  220. return m_values.empty();
  221. }
  222. template <class BC, class FC>
  223. inline auto xoptional_sequence<BC, FC>::size() const noexcept -> size_type
  224. {
  225. return m_values.size();
  226. }
  227. template <class BC, class FC>
  228. inline auto xoptional_sequence<BC, FC>::max_size() const noexcept -> size_type
  229. {
  230. return m_values.max_size();
  231. }
  232. template <class BC, class FC>
  233. inline auto xoptional_sequence<BC, FC>::at(size_type i) -> reference
  234. {
  235. return reference(m_values.at(i), m_flags.at(i));
  236. }
  237. template <class BC, class FC>
  238. inline auto xoptional_sequence<BC, FC>::at(size_type i) const -> const_reference
  239. {
  240. return const_reference(m_values.at(i), m_flags.at(i));
  241. }
  242. template <class BC, class FC>
  243. inline auto xoptional_sequence<BC, FC>::operator[](size_type i) -> reference
  244. {
  245. return reference(m_values[i], m_flags[i]);
  246. }
  247. template <class BC, class FC>
  248. inline auto xoptional_sequence<BC, FC>::operator[](size_type i) const -> const_reference
  249. {
  250. return const_reference(m_values[i], m_flags[i]);
  251. }
  252. template <class BC, class FC>
  253. inline auto xoptional_sequence<BC, FC>::front() -> reference
  254. {
  255. return reference(m_values.front(), m_flags.front());
  256. }
  257. template <class BC, class FC>
  258. inline auto xoptional_sequence<BC, FC>::front() const -> const_reference
  259. {
  260. return const_reference(m_values.front(), m_flags.front());
  261. }
  262. template <class BC, class FC>
  263. inline auto xoptional_sequence<BC, FC>::back() -> reference
  264. {
  265. return reference(m_values.back(), m_flags.back());
  266. }
  267. template <class BC, class FC>
  268. inline auto xoptional_sequence<BC, FC>::back() const -> const_reference
  269. {
  270. return const_reference(m_values.back(), m_flags.back());
  271. }
  272. template <class BC, class FC>
  273. inline auto xoptional_sequence<BC, FC>::begin() noexcept -> iterator
  274. {
  275. return iterator(m_values.begin(), m_flags.begin());
  276. }
  277. template <class BC, class FC>
  278. inline auto xoptional_sequence<BC, FC>::end() noexcept -> iterator
  279. {
  280. return iterator(m_values.end(), m_flags.end());
  281. }
  282. template <class BC, class FC>
  283. inline auto xoptional_sequence<BC, FC>::begin() const noexcept -> const_iterator
  284. {
  285. return cbegin();
  286. }
  287. template <class BC, class FC>
  288. inline auto xoptional_sequence<BC, FC>::end() const noexcept -> const_iterator
  289. {
  290. return cend();
  291. }
  292. template <class BC, class FC>
  293. inline auto xoptional_sequence<BC, FC>::cbegin() const noexcept -> const_iterator
  294. {
  295. return const_iterator(m_values.cbegin(), m_flags.cbegin());
  296. }
  297. template <class BC, class FC>
  298. inline auto xoptional_sequence<BC, FC>::cend() const noexcept -> const_iterator
  299. {
  300. return const_iterator(m_values.cend(), m_flags.cend());
  301. }
  302. template <class BC, class FC>
  303. inline auto xoptional_sequence<BC, FC>::rbegin() noexcept -> reverse_iterator
  304. {
  305. return reverse_iterator(m_values.rbegin(), m_flags.rbegin());
  306. }
  307. template <class BC, class FC>
  308. inline auto xoptional_sequence<BC, FC>::rend() noexcept -> reverse_iterator
  309. {
  310. return reverse_iterator(m_values.rend(), m_flags.rend());
  311. }
  312. template <class BC, class FC>
  313. inline auto xoptional_sequence<BC, FC>::rbegin() const noexcept -> const_reverse_iterator
  314. {
  315. return crbegin();
  316. }
  317. template <class BC, class FC>
  318. inline auto xoptional_sequence<BC, FC>::rend() const noexcept -> const_reverse_iterator
  319. {
  320. return crend();
  321. }
  322. template <class BC, class FC>
  323. inline auto xoptional_sequence<BC, FC>::crbegin() const noexcept -> const_reverse_iterator
  324. {
  325. return const_reverse_iterator(m_values.crbegin(), m_flags.crbegin());
  326. }
  327. template <class BC, class FC>
  328. inline auto xoptional_sequence<BC, FC>::crend() const noexcept -> const_reverse_iterator
  329. {
  330. return const_reverse_iterator(m_values.crend(), m_flags.crend());
  331. }
  332. template <class BC, class FC>
  333. inline auto xoptional_sequence<BC, FC>::value() && noexcept -> base_container_type
  334. {
  335. return m_values;
  336. }
  337. template <class BC, class FC>
  338. inline auto xoptional_sequence<BC, FC>::value() & noexcept -> base_container_type&
  339. {
  340. return m_values;
  341. }
  342. template <class BC, class FC>
  343. inline auto xoptional_sequence<BC, FC>::value() const & noexcept -> const base_container_type&
  344. {
  345. return m_values;
  346. }
  347. template <class BC, class FC>
  348. inline auto xoptional_sequence<BC, FC>::has_value() && noexcept-> flag_container_type
  349. {
  350. return m_flags;
  351. }
  352. template <class BC, class FC>
  353. inline auto xoptional_sequence<BC, FC>::has_value() & noexcept -> flag_container_type&
  354. {
  355. return m_flags;
  356. }
  357. template <class BC, class FC>
  358. inline auto xoptional_sequence<BC, FC>::has_value() const & noexcept -> const flag_container_type&
  359. {
  360. return m_flags;
  361. }
  362. template <class BC, class FC>
  363. inline bool operator==(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
  364. {
  365. return lhs.value() == rhs.value() && lhs.has_value() == rhs.has_value();
  366. }
  367. template <class BC, class FC>
  368. inline bool operator!=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
  369. {
  370. return !(lhs == rhs);
  371. }
  372. template <class BC, class FC>
  373. inline bool operator<(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
  374. {
  375. return lhs.value() < rhs.value() && lhs.has_value() == rhs.has_value();
  376. }
  377. template <class BC, class FC>
  378. inline bool operator<=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
  379. {
  380. return lhs.value() <= rhs.value() && lhs.has_value() == rhs.has_value();
  381. }
  382. template <class BC, class FC>
  383. inline bool operator>(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
  384. {
  385. return lhs.value() > rhs.value() && lhs.has_value() == rhs.has_value();
  386. }
  387. template <class BC, class FC>
  388. inline bool operator>=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
  389. {
  390. return lhs.value() >= rhs.value() && lhs.has_value() == rhs.has_value();
  391. }
  392. /**********************************
  393. * xoptional_array implementation *
  394. **********************************/
  395. template <class T, std::size_t I, class BC>
  396. xoptional_array<T, I, BC>::xoptional_array(size_type s, const base_value_type& v)
  397. : base_type(s, v)
  398. {
  399. }
  400. template <class T, std::size_t I, class BC>
  401. template <class CTO, class CBO>
  402. xoptional_array<T, I, BC>::xoptional_array(size_type s, const xoptional<CTO, CBO>& v)
  403. : base_type(s, v)
  404. {
  405. }
  406. /*******************************************************
  407. * xoptional_array and xoptional_vector implementation *
  408. *******************************************************/
  409. template <class T, class A, class BC>
  410. xoptional_vector<T, A, BC>::xoptional_vector(size_type s, const base_value_type& v)
  411. : base_type(s, v)
  412. {
  413. }
  414. template <class T, class A, class BC>
  415. template <class CTO, class CBO>
  416. xoptional_vector<T, A, BC>::xoptional_vector(size_type s, const xoptional<CTO, CBO>& v)
  417. : base_type(s, v)
  418. {
  419. }
  420. template <class T, class A, class BC>
  421. void xoptional_vector<T, A, BC>::resize(size_type s)
  422. {
  423. // Default to missing
  424. this->m_values.resize(s);
  425. this->m_flags.resize(s, false);
  426. }
  427. template <class T, class A, class BC>
  428. void xoptional_vector<T, A, BC>::resize(size_type s, const base_value_type& v)
  429. {
  430. this->m_values.resize(s, v);
  431. this->m_flags.resize(s, true);
  432. }
  433. template <class T, class A, class BC>
  434. template <class CTO, class CBO>
  435. void xoptional_vector<T, A, BC>::resize(size_type s, const xoptional<CTO, CBO>& v)
  436. {
  437. this->m_values.resize(s, v.value());
  438. this->m_flags.resize(s, v.has_value());
  439. }
  440. /*************************************
  441. * xoptional_iterator implementation *
  442. *************************************/
  443. template <class ITV, class ITB>
  444. xoptional_iterator<ITV, ITB>::xoptional_iterator(ITV itv, ITB itb)
  445. : m_itv(itv), m_itb(itb)
  446. {
  447. }
  448. template <class ITV, class ITB>
  449. auto xoptional_iterator<ITV, ITB>::operator++() -> self_type&
  450. {
  451. ++m_itv;
  452. ++m_itb;
  453. return *this;
  454. }
  455. template <class ITV, class ITB>
  456. auto xoptional_iterator<ITV, ITB>::operator--() -> self_type&
  457. {
  458. --m_itv;
  459. --m_itb;
  460. return *this;
  461. }
  462. template <class ITV, class ITB>
  463. auto xoptional_iterator<ITV, ITB>::operator+=(difference_type n) -> self_type&
  464. {
  465. m_itv += n;
  466. m_itb += n;
  467. return *this;
  468. }
  469. template <class ITV, class ITB>
  470. auto xoptional_iterator<ITV, ITB>::operator-=(difference_type n) -> self_type&
  471. {
  472. m_itv -= n;
  473. m_itb -= n;
  474. return *this;
  475. }
  476. template <class ITV, class ITB>
  477. auto xoptional_iterator<ITV, ITB>::operator-(const self_type& rhs) const -> difference_type
  478. {
  479. return m_itv - rhs.m_itv;
  480. }
  481. template <class ITV, class ITB>
  482. auto xoptional_iterator<ITV, ITB>::operator*() const -> reference
  483. {
  484. return reference(*m_itv, *m_itb);
  485. }
  486. template <class ITV, class ITB>
  487. auto xoptional_iterator<ITV, ITB>::operator-> () const -> pointer
  488. {
  489. return pointer(operator*());
  490. }
  491. template <class ITV, class ITB>
  492. bool xoptional_iterator<ITV, ITB>::operator==(const self_type& rhs) const
  493. {
  494. return m_itv == rhs.m_itv && m_itb == rhs.m_itb;
  495. }
  496. template <class ITV, class ITB>
  497. bool xoptional_iterator<ITV, ITB>::operator<(const self_type& rhs) const
  498. {
  499. return m_itv < rhs.m_itv && m_itb < rhs.m_itb;
  500. }
  501. }
  502. #endif