/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_CONTAINER_CONTAINER_HOLDER_HPP #define SPROUT_CONTAINER_CONTAINER_HOLDER_HPP #include #include #include #include #include #include #include #include namespace sprout { // // container_holder // template class container_holder : public sprout::container_traits_facade { private: typedef sprout::container_traits_facade facade_type; public: typedef Container container_type; typedef container_type internal_type; typedef typename facade_type::iterator iterator; typedef typename facade_type::const_iterator const_iterator; typedef typename facade_type::reference reference; typedef typename facade_type::const_reference const_reference; typedef typename facade_type::size_type size_type; typedef typename facade_type::difference_type difference_type; typedef typename facade_type::pointer pointer; typedef typename facade_type::const_pointer const_pointer; typedef internal_type& param_type; typedef internal_type const& const_param_type; typedef sprout::value_holder holder_type; protected: holder_type container; public: SPROUT_CONSTEXPR container_holder() : container() {} explicit SPROUT_CONSTEXPR container_holder(param_type x) : container(x) {} container_holder(container_holder const&) = default; SPROUT_CXX14_CONSTEXPR void swap(container_holder& other) SPROUT_NOEXCEPT_IF_EXPR(sprout::swap(other.container, container)) { sprout::swap(other.container, container); } // iterators: SPROUT_CXX14_CONSTEXPR iterator begin() { return sprout::begin(*container); } SPROUT_CONSTEXPR const_iterator begin() const { return sprout::begin(*container); } SPROUT_CXX14_CONSTEXPR iterator end() { return sprout::end(*container); } SPROUT_CONSTEXPR const_iterator end() const { return sprout::end(*container); } SPROUT_CONSTEXPR const_iterator cbegin() const { return sprout::begin(*container); } SPROUT_CONSTEXPR const_iterator cend() const { return sprout::end(*container); } // capacity: SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { return sprout::size(*container); } SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { return sprout::empty(*container); } SPROUT_CXX14_CONSTEXPR param_type get_internal() { return *container; } SPROUT_CONSTEXPR const_param_type get_internal() const { return *container; } // element access: SPROUT_CXX14_CONSTEXPR reference operator[](size_type i) { return *sprout::next(begin(), i); } SPROUT_CONSTEXPR const_reference operator[](size_type i) const { return *sprout::next(begin(), i); } SPROUT_CXX14_CONSTEXPR reference at(size_type i) { return i < size() ? (*this)[i] : (throw std::out_of_range("container_holder<>: index out of range"), (*this)[i]) ; } SPROUT_CONSTEXPR const_reference at(size_type i) const { return i < size() ? (*this)[i] : (throw std::out_of_range("container_holder<>: index out of range"), (*this)[i]) ; } SPROUT_CXX14_CONSTEXPR reference front() { return *begin(); } SPROUT_CONSTEXPR const_reference front() const { return *begin(); } SPROUT_CXX14_CONSTEXPR reference back() { return *sprout::next(begin(), size() - 1); } SPROUT_CONSTEXPR const_reference back() const { return *sprout::next(begin(), size() - 1); } }; // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap(sprout::container_holder& lhs, sprout::container_holder& rhs) SPROUT_NOEXCEPT_IF_EXPR(lhs.swap(rhs)) { lhs.swap(rhs); } // // container_construct_traits // template struct container_construct_traits > { public: typedef typename sprout::container_construct_traits::copied_type copied_type; public: template static SPROUT_CONSTEXPR copied_type deep_copy(Cont&& cont) { return sprout::deep_copy(sprout::get_internal(SPROUT_FORWARD(Cont, cont))); } template static SPROUT_CONSTEXPR copied_type make(Args&&... args) { return sprout::make(SPROUT_FORWARD(Args, args)...); } template static SPROUT_CONSTEXPR copied_type remake(Cont&& cont, typename sprout::container_traits::difference_type size, Args&&... args) { return sprout::remake(sprout::get_internal(SPROUT_FORWARD(Cont, cont)), size, SPROUT_FORWARD(Args, args)...); } }; // // sub_container_traits // template struct sub_container_traits > { private: static typename sprout::container_holder::param_type call(sprout::container_holder& cont) { return cont.get_internal(); } static SPROUT_CONSTEXPR typename sprout::container_holder::const_param_type call(sprout::container_holder const& cont) { return cont.get_internal(); } public: template struct internal { public: typedef decltype(call(std::declval())) type; }; public: template static SPROUT_CONSTEXPR typename internal::type get_internal(Cont&& cont) { return call(SPROUT_FORWARD(Cont, cont)); } }; } // namespace sprout #endif // #ifndef SPROUT_CONTAINER_CONTAINER_HOLDER_HPP