/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XTL_OPTIONAL_SEQUENCE_HPP #define XTL_OPTIONAL_SEQUENCE_HPP #include #include #include #include #include #include #include #include "xdynamic_bitset.hpp" #include "xiterator_base.hpp" #include "xoptional.hpp" #include "xsequence.hpp" namespace xtl { /************************************** * Optimized 1-D xoptional containers * **************************************/ template class xoptional_iterator; template class xoptional_sequence { public: // Internal typedefs using base_container_type = BC; using base_value_type = typename base_container_type::value_type; using base_reference = typename base_container_type::reference; using base_const_reference = typename base_container_type::const_reference; using flag_container_type = FC; using flag_type = typename flag_container_type::value_type; using flag_reference = typename flag_container_type::reference; using flag_const_reference = typename flag_container_type::const_reference; // Container typedefs using value_type = xoptional; using reference = xoptional; using const_reference = xoptional; using pointer = xclosure_pointer; using const_pointer = xclosure_pointer; // Other typedefs using size_type = typename base_container_type::size_type; using difference_type = typename base_container_type::difference_type; using iterator = xoptional_iterator; using const_iterator = xoptional_iterator; using reverse_iterator = xoptional_iterator; using const_reverse_iterator = xoptional_iterator; bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; reference at(size_type i); const_reference at(size_type i) const; reference operator[](size_type i); const_reference operator[](size_type i) const; reference front(); const_reference front() const; reference back(); const_reference back() const; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; reverse_iterator rbegin() noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rbegin() const noexcept; const_reverse_iterator rend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; base_container_type value() && noexcept; base_container_type& value() & noexcept; const base_container_type& value() const & noexcept; flag_container_type has_value() && noexcept; flag_container_type& has_value() & noexcept; const flag_container_type& has_value() const & noexcept; protected: xoptional_sequence() = default; xoptional_sequence(size_type s, const base_value_type& v); template xoptional_sequence(size_type s, const xoptional& v); ~xoptional_sequence() = default; xoptional_sequence(const xoptional_sequence&) = default; xoptional_sequence& operator=(const xoptional_sequence&) = default; xoptional_sequence(xoptional_sequence&&) = default; xoptional_sequence& operator=(xoptional_sequence&&) = default; base_container_type m_values; flag_container_type m_flags; }; template bool operator==(const xoptional_sequence& lhs, const xoptional_sequence& rhs); template bool operator!=(const xoptional_sequence& lhs, const xoptional_sequence& rhs); template bool operator<(const xoptional_sequence& lhs, const xoptional_sequence& rhs); template bool operator<=(const xoptional_sequence& lhs, const xoptional_sequence& rhs); template bool operator>(const xoptional_sequence& lhs, const xoptional_sequence& rhs); template bool operator>=(const xoptional_sequence& lhs, const xoptional_sequence& rhs); /******************************** * xoptional_array declarations * ********************************/ // There is no value_type in std::bitset ... template > class xoptional_array : public xoptional_sequence, BC> { public: using self_type = xoptional_array; using base_container_type = std::array; using flag_container_type = BC; using base_type = xoptional_sequence; using base_value_type = typename base_type::base_value_type; using size_type = typename base_type::size_type; xoptional_array() = default; xoptional_array(size_type s, const base_value_type& v); template xoptional_array(size_type s, const xoptional& v); }; /******************** * xoptional_vector * ********************/ template , class BC = xdynamic_bitset> class xoptional_vector : public xoptional_sequence, BC> { public: using self_type = xoptional_vector; using base_container_type = std::vector; using flag_container_type = BC; using base_type = xoptional_sequence; using base_value_type = typename base_type::base_value_type; using allocator_type = A; using value_type = typename base_type::value_type; using size_type = typename base_type::size_type; using difference_type = typename base_type::difference_type; using reference = typename base_type::reference; using const_reference = typename base_type::const_reference; using pointer = typename base_type::pointer; using const_pointer = typename base_type::const_pointer; using iterator = typename base_type::iterator; using const_iterator = typename base_type::const_iterator; using reverse_iterator = typename base_type::reverse_iterator; using const_reverse_iterator = typename base_type::const_reverse_iterator; xoptional_vector() = default; xoptional_vector(size_type, const base_value_type&); template xoptional_vector(size_type, const xoptional&); void resize(size_type); void resize(size_type, const base_value_type&); template void resize(size_type, const xoptional&); }; /********************************** * xoptional_iterator declaration * **********************************/ template struct xoptional_iterator_traits { using iterator_type = xoptional_iterator; using value_type = xoptional; using reference = xoptional; using pointer = xclosure_pointer; using difference_type = typename ITV::difference_type; }; template class xoptional_iterator : public xrandom_access_iterator_base2> { public: using self_type = xoptional_iterator; using base_type = xrandom_access_iterator_base2>; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using pointer = typename base_type::pointer; using difference_type = typename base_type::difference_type; xoptional_iterator() = default; xoptional_iterator(ITV itv, ITB itb); self_type& operator++(); self_type& operator--(); self_type& operator+=(difference_type n); self_type& operator-=(difference_type n); difference_type operator-(const self_type& rhs) const; reference operator*() const; pointer operator->() const; bool operator==(const self_type& rhs) const; bool operator<(const self_type& rhs) const; private: ITV m_itv; ITB m_itb; }; /************************************* * xoptional_sequence implementation * *************************************/ template inline xoptional_sequence::xoptional_sequence(size_type s, const base_value_type& v) : m_values(make_sequence(s, v)), m_flags(make_sequence(s, true)) { } template template inline xoptional_sequence::xoptional_sequence(size_type s, const xoptional& v) : m_values(make_sequence(s, v.value())), m_flags(make_sequence(s, v.has_value())) { } template inline auto xoptional_sequence::empty() const noexcept -> bool { return m_values.empty(); } template inline auto xoptional_sequence::size() const noexcept -> size_type { return m_values.size(); } template inline auto xoptional_sequence::max_size() const noexcept -> size_type { return m_values.max_size(); } template inline auto xoptional_sequence::at(size_type i) -> reference { return reference(m_values.at(i), m_flags.at(i)); } template inline auto xoptional_sequence::at(size_type i) const -> const_reference { return const_reference(m_values.at(i), m_flags.at(i)); } template inline auto xoptional_sequence::operator[](size_type i) -> reference { return reference(m_values[i], m_flags[i]); } template inline auto xoptional_sequence::operator[](size_type i) const -> const_reference { return const_reference(m_values[i], m_flags[i]); } template inline auto xoptional_sequence::front() -> reference { return reference(m_values.front(), m_flags.front()); } template inline auto xoptional_sequence::front() const -> const_reference { return const_reference(m_values.front(), m_flags.front()); } template inline auto xoptional_sequence::back() -> reference { return reference(m_values.back(), m_flags.back()); } template inline auto xoptional_sequence::back() const -> const_reference { return const_reference(m_values.back(), m_flags.back()); } template inline auto xoptional_sequence::begin() noexcept -> iterator { return iterator(m_values.begin(), m_flags.begin()); } template inline auto xoptional_sequence::end() noexcept -> iterator { return iterator(m_values.end(), m_flags.end()); } template inline auto xoptional_sequence::begin() const noexcept -> const_iterator { return cbegin(); } template inline auto xoptional_sequence::end() const noexcept -> const_iterator { return cend(); } template inline auto xoptional_sequence::cbegin() const noexcept -> const_iterator { return const_iterator(m_values.cbegin(), m_flags.cbegin()); } template inline auto xoptional_sequence::cend() const noexcept -> const_iterator { return const_iterator(m_values.cend(), m_flags.cend()); } template inline auto xoptional_sequence::rbegin() noexcept -> reverse_iterator { return reverse_iterator(m_values.rbegin(), m_flags.rbegin()); } template inline auto xoptional_sequence::rend() noexcept -> reverse_iterator { return reverse_iterator(m_values.rend(), m_flags.rend()); } template inline auto xoptional_sequence::rbegin() const noexcept -> const_reverse_iterator { return crbegin(); } template inline auto xoptional_sequence::rend() const noexcept -> const_reverse_iterator { return crend(); } template inline auto xoptional_sequence::crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(m_values.crbegin(), m_flags.crbegin()); } template inline auto xoptional_sequence::crend() const noexcept -> const_reverse_iterator { return const_reverse_iterator(m_values.crend(), m_flags.crend()); } template inline auto xoptional_sequence::value() && noexcept -> base_container_type { return m_values; } template inline auto xoptional_sequence::value() & noexcept -> base_container_type& { return m_values; } template inline auto xoptional_sequence::value() const & noexcept -> const base_container_type& { return m_values; } template inline auto xoptional_sequence::has_value() && noexcept-> flag_container_type { return m_flags; } template inline auto xoptional_sequence::has_value() & noexcept -> flag_container_type& { return m_flags; } template inline auto xoptional_sequence::has_value() const & noexcept -> const flag_container_type& { return m_flags; } template inline bool operator==(const xoptional_sequence& lhs, const xoptional_sequence& rhs) { return lhs.value() == rhs.value() && lhs.has_value() == rhs.has_value(); } template inline bool operator!=(const xoptional_sequence& lhs, const xoptional_sequence& rhs) { return !(lhs == rhs); } template inline bool operator<(const xoptional_sequence& lhs, const xoptional_sequence& rhs) { return lhs.value() < rhs.value() && lhs.has_value() == rhs.has_value(); } template inline bool operator<=(const xoptional_sequence& lhs, const xoptional_sequence& rhs) { return lhs.value() <= rhs.value() && lhs.has_value() == rhs.has_value(); } template inline bool operator>(const xoptional_sequence& lhs, const xoptional_sequence& rhs) { return lhs.value() > rhs.value() && lhs.has_value() == rhs.has_value(); } template inline bool operator>=(const xoptional_sequence& lhs, const xoptional_sequence& rhs) { return lhs.value() >= rhs.value() && lhs.has_value() == rhs.has_value(); } /********************************** * xoptional_array implementation * **********************************/ template xoptional_array::xoptional_array(size_type s, const base_value_type& v) : base_type(s, v) { } template template xoptional_array::xoptional_array(size_type s, const xoptional& v) : base_type(s, v) { } /******************************************************* * xoptional_array and xoptional_vector implementation * *******************************************************/ template xoptional_vector::xoptional_vector(size_type s, const base_value_type& v) : base_type(s, v) { } template template xoptional_vector::xoptional_vector(size_type s, const xoptional& v) : base_type(s, v) { } template void xoptional_vector::resize(size_type s) { // Default to missing this->m_values.resize(s); this->m_flags.resize(s, false); } template void xoptional_vector::resize(size_type s, const base_value_type& v) { this->m_values.resize(s, v); this->m_flags.resize(s, true); } template template void xoptional_vector::resize(size_type s, const xoptional& v) { this->m_values.resize(s, v.value()); this->m_flags.resize(s, v.has_value()); } /************************************* * xoptional_iterator implementation * *************************************/ template xoptional_iterator::xoptional_iterator(ITV itv, ITB itb) : m_itv(itv), m_itb(itb) { } template auto xoptional_iterator::operator++() -> self_type& { ++m_itv; ++m_itb; return *this; } template auto xoptional_iterator::operator--() -> self_type& { --m_itv; --m_itb; return *this; } template auto xoptional_iterator::operator+=(difference_type n) -> self_type& { m_itv += n; m_itb += n; return *this; } template auto xoptional_iterator::operator-=(difference_type n) -> self_type& { m_itv -= n; m_itb -= n; return *this; } template auto xoptional_iterator::operator-(const self_type& rhs) const -> difference_type { return m_itv - rhs.m_itv; } template auto xoptional_iterator::operator*() const -> reference { return reference(*m_itv, *m_itb); } template auto xoptional_iterator::operator-> () const -> pointer { return pointer(operator*()); } template bool xoptional_iterator::operator==(const self_type& rhs) const { return m_itv == rhs.m_itv && m_itb == rhs.m_itb; } template bool xoptional_iterator::operator<(const self_type& rhs) const { return m_itv < rhs.m_itv && m_itb < rhs.m_itb; } } #endif