#ifndef SPROUT_SUB_ARRAY_HPP #define SPROUT_SUB_ARRAY_HPP #include #include #include #include #include #include #include #include #include #include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT_DETAIL #include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT_DETAIL namespace sprout { namespace detail { struct is_non_reference_array_tag {}; struct is_not_non_reference_array_tag {}; template class sub_array_impl { protected: typedef Container container_type; typedef typename std::remove_reference::type fixed_container_type; typedef typename std::remove_const::type internal_type; protected: SPROUT_STATIC_CONSTEXPR bool is_reference = std::is_reference::value; SPROUT_STATIC_CONSTEXPR bool is_const = std::is_const::value; protected: typedef typename sprout::fixed_container_traits::value_type value_type; typedef typename sprout::detail::if_c< is_const, typename sprout::fixed_container_traits::const_iterator, typename sprout::fixed_container_traits::iterator >::type iterator; typedef typename sprout::fixed_container_traits::const_iterator const_iterator; typedef typename sprout::detail::if_c< is_const, typename sprout::fixed_container_traits::const_reference, typename sprout::fixed_container_traits::reference >::type reference; typedef typename sprout::fixed_container_traits::const_reference const_reference; typedef typename sprout::fixed_container_traits::size_type size_type; typedef typename sprout::fixed_container_traits::difference_type difference_type; typedef typename sprout::detail::if_c< is_const, typename sprout::fixed_container_traits::const_pointer, typename sprout::fixed_container_traits::pointer >::type pointer; typedef typename sprout::fixed_container_traits::const_pointer const_pointer; protected: SPROUT_STATIC_CONSTEXPR size_type static_size = sprout::fixed_container_traits::fixed_size; SPROUT_STATIC_CONSTEXPR size_type fixed_size = static_size; protected: typedef typename sprout::detail::if_c< is_reference, fixed_container_type*, typename std::remove_const::type >::type holder_type; typedef typename sprout::detail::if_c< is_reference, fixed_container_type&, fixed_container_type const& >::type param_type; typedef fixed_container_type const& const_param_type; protected: typedef typename sprout::detail::if_c< std::is_array::value, sprout::detail::is_non_reference_array_tag, sprout::detail::is_not_non_reference_array_tag >::type array_tag; protected: template static SPROUT_CONSTEXPR typename std::enable_if< std::is_reference::value, holder_type >::type to_holder(param_type arr) { return &arr; } template static SPROUT_CONSTEXPR typename std::enable_if< !std::is_reference::value, holder_type const& >::type to_holder(param_type arr) { return arr; } template static SPROUT_CONSTEXPR typename std::enable_if< std::is_reference::value, param_type >::type to_param(holder_type arr) { return *arr; } template static SPROUT_CONSTEXPR typename std::enable_if< !std::is_reference::value, param_type >::type to_param(holder_type& arr) { return arr; } template static SPROUT_CONSTEXPR typename std::enable_if< !std::is_reference::value, param_type >::type to_param(holder_type const& arr) { return arr; } template static SPROUT_CONSTEXPR typename std::enable_if< std::is_reference::value, const_param_type >::type to_const_param(holder_type arr) { return *arr; } template static SPROUT_CONSTEXPR typename std::enable_if< !std::is_reference::value, const_param_type >::type to_const_param(holder_type const& arr) { return arr; } protected: holder_type array_; difference_type first_; difference_type last_; public: sub_array_impl() = default; protected: template SPROUT_CONSTEXPR sub_array_impl( ContainerTag, param_type arr, sprout::index_tuple, const_iterator first, const_iterator last, typename std::enable_if::value>::type* = 0 ) : array_{to_holder(arr)[Indexes]...} , first_(NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::cbegin(arr), first)) , last_(NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::cbegin(arr), last)) {} template SPROUT_CONSTEXPR sub_array_impl( ContainerTag, param_type arr, sprout::index_tuple, const_iterator first, const_iterator last, typename std::enable_if::value>::type* = 0 ) : array_(to_holder(arr)) , first_(NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::cbegin(arr), first)) , last_(NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::cbegin(arr), last)) {} template SPROUT_CONSTEXPR sub_array_impl( ContainerTag, param_type arr, sprout::index_tuple, difference_type first, difference_type last, typename std::enable_if::value>::type* = 0 ) : array_{to_holder(arr)[Indexes]...} , first_(first) , last_(last) {} template SPROUT_CONSTEXPR sub_array_impl( ContainerTag, param_type arr, sprout::index_tuple, difference_type first, difference_type last, typename std::enable_if::value>::type* = 0 ) : array_(to_holder(arr)) , first_(first) , last_(last) {} }; } // namespace detail // // sub_array // template class sub_array : private sprout::detail::sub_array_impl { private: typedef sprout::detail::sub_array_impl impl_type; public: typedef typename impl_type::container_type container_type; typedef typename impl_type::fixed_container_type fixed_container_type; typedef typename impl_type::internal_type internal_type; typedef sub_array::clone_type> clone_type; public: SPROUT_STATIC_CONSTEXPR bool is_reference = impl_type::is_reference; SPROUT_STATIC_CONSTEXPR bool is_const = impl_type::is_const; public: typedef typename impl_type::value_type value_type; typedef typename impl_type::iterator iterator; typedef typename impl_type::const_iterator const_iterator; typedef typename impl_type::reference reference; typedef typename impl_type::const_reference const_reference; typedef typename impl_type::size_type size_type; typedef typename impl_type::difference_type difference_type; typedef typename impl_type::pointer pointer; typedef typename impl_type::const_pointer const_pointer; public: SPROUT_STATIC_CONSTEXPR size_type static_size = impl_type::static_size; SPROUT_STATIC_CONSTEXPR size_type fixed_size = impl_type::fixed_size; public: typedef typename impl_type::holder_type holder_type; typedef typename impl_type::param_type param_type; typedef typename impl_type::const_param_type const_param_type; private: typedef typename impl_type::array_tag array_tag; private: using impl_type::array_; using impl_type::first_; using impl_type::last_; public: sub_array() = default; SPROUT_CONSTEXPR sub_array(param_type arr, const_iterator first, const_iterator last) : impl_type( array_tag(), arr, typename sprout::index_range<0, fixed_size>::type(), first, last ) {} SPROUT_CONSTEXPR sub_array(param_type arr, difference_type first, difference_type last) : impl_type( array_tag(), arr, typename sprout::index_range<0, fixed_size>::type(), first, last ) {} SPROUT_CONSTEXPR sub_array(sub_array const& other, const_iterator first, const_iterator last) : impl_type( array_tag(), impl_type::template to_param(other.array_), typename sprout::index_range<0, fixed_size>::type(), NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::begin(other.get_array()), first), NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::begin(other.get_array()), last) ) {} SPROUT_CONSTEXPR sub_array(sub_array const& other, difference_type first, difference_type last) : impl_type( array_tag(), impl_type::template to_param(other.array_), typename sprout::index_range<0, fixed_size>::type(), first + other.first_, last + other.first_ ) {} param_type get_fixed() { return impl_type::template to_param(array_); } SPROUT_CONSTEXPR const_param_type get_fixed() const { return impl_type::template to_const_param(array_); } SPROUT_CONSTEXPR const_param_type get_cfixed() const { return impl_type::template to_const_param(array_); } param_type get_array() { return impl_type::template to_param(array_); } SPROUT_CONSTEXPR const_param_type get_array() const { return impl_type::template to_const_param(array_); } SPROUT_CONSTEXPR size_type size() const { return last_ - first_; } SPROUT_CONSTEXPR bool empty() const { return size() == 0; } SPROUT_CONSTEXPR size_type max_size() const { return size(); } void rangecheck(size_type i) const { if (i >= size()) { throw std::out_of_range("sub_array<>: index out of range"); } } iterator begin() { return sprout::begin(get_array()) + first_; } SPROUT_CONSTEXPR const_iterator begin() const { return sprout::begin(get_array()) + first_; } SPROUT_CONSTEXPR const_iterator cbegin() const { return sprout::begin(get_array()) + first_; } iterator end() { return sprout::begin(get_array()) + last_; } SPROUT_CONSTEXPR const_iterator end() const { return sprout::begin(get_array()) + last_; } SPROUT_CONSTEXPR const_iterator cend() const { return sprout::begin(get_array()) + last_; } reference operator[](size_type i) { return *(sprout::begin(get_array()) + first_ + i); } SPROUT_CONSTEXPR const_reference operator[](size_type i) const { return *(sprout::begin(get_array()) + first_ + i); } reference at(size_type i) { rangecheck(i); return *(sprout::begin(get_array()) + first_ + i); } const_reference at(size_type i) const { rangecheck(i); return *(sprout::begin(get_array()) + first_ + i); } reference front() { return *(sprout::begin(get_array()) + first_); } SPROUT_CONSTEXPR const_reference front() const { return *(sprout::begin(get_array()) + first_); } reference back() { return *(sprout::begin(get_array()) + (last_ - 1)); } SPROUT_CONSTEXPR const_reference back() const { return *(sprout::begin(get_array()) + (last_ - 1)); } pointer data() { return get_array().data() + first_; } SPROUT_CONSTEXPR const_pointer data() const { return get_array().data() + first_; } pointer c_array() { return data(); } void assign (const_reference value) { fill(value); } void fill(const_reference value) { std::fill_n(begin(), size(), value); } template void swap(sub_array& other) { using std::swap; swap(other.array_, array_); swap(other.first_, first_); swap(other.last_, last_); } template sub_array& operator=(sub_array const& rhs) { array_ = rhs.array_; first_ = rhs.first_; last_ = rhs.last_; return *this; } template sub_array& operator=(sub_array&& rhs) { array_ = std::move(rhs.array_); first_ = std::move(rhs.first_); last_ = std::move(rhs.last_); return *this; } }; template SPROUT_CONSTEXPR inline bool operator==(sprout::sub_array const& lhs, sprout::sub_array const& rhs) { return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::equal(sprout::begin(lhs), sprout::end(lhs), sprout::begin(rhs)); } template SPROUT_CONSTEXPR inline bool operator!=(sprout::sub_array const& lhs, sprout::sub_array const& rhs) { return !(lhs == rhs); } template SPROUT_CONSTEXPR inline bool operator<(sprout::sub_array const& lhs, sprout::sub_array const& rhs) { return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::lexicographical_compare(sprout::begin(lhs), sprout::end(lhs), sprout::begin(rhs), sprout::end(rhs)); } template SPROUT_CONSTEXPR inline bool operator>(sprout::sub_array const& lhs, sprout::sub_array const& rhs) { return rhs < lhs; } template SPROUT_CONSTEXPR inline bool operator<=(sprout::sub_array const& lhs, sprout::sub_array const& rhs) { return !(rhs < lhs); } template SPROUT_CONSTEXPR inline bool operator>=(sprout::sub_array const& lhs, sprout::sub_array const& rhs) { return !(lhs < rhs); } // // swap // template inline void swap(sprout::sub_array& lhs, sprout::sub_array& rhs) { lhs.swap(rhs); } // // fixed_container_traits // template struct fixed_container_traits > : public sprout::detail::fixed_container_traits_base > { public: typedef typename sprout::sub_array::fixed_container_type fixed_container_type; typedef typename sprout::sub_array::internal_type internal_type; typedef typename sprout::sub_array::clone_type clone_type; public: SPROUT_STATIC_CONSTEXPR typename sprout::detail::fixed_container_traits_base >::size_type fixed_size = std::tuple_size::type>::value ; }; // // rebind_fixed_size // template struct rebind_fixed_size > { public: template >::size_type S> struct apply { public: typedef sprout::sub_array< typename sprout::rebind_fixed_size< typename sprout::fixed_container_traits >::internal_type >::template apply::type > type; }; }; // // get_fixed_functor // template struct get_fixed_functor > { private: typedef typename sprout::fixed_container_traits >::fixed_container_type fixed_container_type; public: fixed_container_type& operator()(sprout::sub_array& cont) const { return cont.get_fixed(); } SPROUT_CONSTEXPR fixed_container_type const& operator()(sprout::sub_array const& cont) const { return cont.get_fixed(); } }; // // clone_functor // template struct clone_functor > { private: typedef typename sprout::fixed_container_traits >::clone_type clone_type; public: clone_type operator()(sprout::sub_array& cont) const { return clone_type(sprout::clone(sprout::get_fixed(cont)), sprout::fixed_begin_offset(cont), sprout::fixed_end_offset(cont)); } SPROUT_CONSTEXPR clone_type operator()(sprout::sub_array const& cont) const { return clone_type(sprout::clone(sprout::get_fixed(cont)), sprout::fixed_begin_offset(cont), sprout::fixed_end_offset(cont)); } }; // // make_clone_functor // template struct make_clone_functor > { private: typedef typename sprout::fixed_container_traits >::clone_type clone_type; typedef typename sprout::fixed_container_traits >::internal_type internal_type; private: SPROUT_CONSTEXPR clone_type make(typename sprout::fixed_container_traits::clone_type const& arr) const { return clone_type(arr, sprout::begin(arr), sprout::end(arr)); } public: template SPROUT_CONSTEXPR clone_type operator()(Args const&... args) const { return make(sprout::make_clone(args...)); } }; // // remake_clone_functor // template struct remake_clone_functor > { private: typedef typename sprout::fixed_container_traits >::clone_type clone_type; typedef typename sprout::fixed_container_traits >::internal_type internal_type; private: template clone_type remake( Other& other, typename sprout::fixed_container_traits >::difference_type size, typename sprout::fixed_container_traits::clone_type const& cloned ) const { return clone_type( cloned, sprout::begin(cloned) + sprout::fixed_begin_offset(other), sprout::begin(cloned) + sprout::fixed_begin_offset(other) + size ); } template SPROUT_CONSTEXPR clone_type remake( Other const& other, typename sprout::fixed_container_traits >::difference_type size, typename sprout::fixed_container_traits::clone_type const& cloned ) const { return clone_type( cloned, sprout::begin(cloned) + sprout::fixed_begin_offset(other), sprout::begin(cloned) + sprout::fixed_begin_offset(other) + size ); } public: template clone_type operator()( Other& other, typename sprout::fixed_container_traits >::difference_type size, Args const&... args ) const { return remake(other, size, sprout::make_clone(args...)); } template SPROUT_CONSTEXPR clone_type operator()( Other const& other, typename sprout::fixed_container_traits >::difference_type size, Args const&... args ) const { return remake(other, size, sprout::make_clone(args...)); } }; namespace detail { template struct is_sub_array_impl { public: typedef std::integral_constant type; SPROUT_STATIC_CONSTEXPR bool value = type::value; }; template struct is_sub_array_impl< T, typename std::enable_if< std::is_same< T, sprout::sub_array >::value >::type > { public: typedef std::integral_constant type; SPROUT_STATIC_CONSTEXPR bool value = type::value; }; } // namespace detail // // is_sub_array // template struct is_sub_array : public sprout::detail::is_sub_array_impl {}; // // sub // template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container& arr, typename sprout::fixed_container_traits >::const_iterator first, typename sprout::fixed_container_traits >::const_iterator last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container& arr, typename sprout::fixed_container_traits >::difference_type first, typename sprout::fixed_container_traits >::difference_type last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container& arr, typename sprout::fixed_container_traits >::const_iterator first ) { return sprout::sub(arr, first, sprout::end(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container& arr, typename sprout::fixed_container_traits >::difference_type first ) { return sprout::sub(arr, first, sprout::size(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container& arr ) { return sprout::sub(arr, sprout::begin(arr), sprout::end(arr)); } // // sub // template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container const& arr, typename sprout::fixed_container_traits >::const_iterator first, typename sprout::fixed_container_traits >::const_iterator last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container const& arr, typename sprout::fixed_container_traits >::difference_type first, typename sprout::fixed_container_traits >::difference_type last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container const& arr, typename sprout::fixed_container_traits >::const_iterator first ) { return sprout::sub(arr, first, sprout::end(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container const& arr, typename sprout::fixed_container_traits >::difference_type first ) { return sprout::sub(arr, first, sprout::size(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub( Container const& arr ) { return sprout::sub(arr, sprout::begin(arr), sprout::end(arr)); } // // sub // template SPROUT_CONSTEXPR inline typename std::enable_if::value, Container>::type sub( Container const& arr, typename sprout::fixed_container_traits::const_iterator first, typename sprout::fixed_container_traits::const_iterator last ) { return Container(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, Container>::type sub( Container const& arr, typename sprout::fixed_container_traits::difference_type first, typename sprout::fixed_container_traits::difference_type last ) { return Container(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, Container>::type sub( Container const& arr, typename sprout::fixed_container_traits::const_iterator first ) { return sprout::sub(arr, first, sprout::end(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, Container>::type sub( Container const& arr, typename sprout::fixed_container_traits::difference_type first ) { return sprout::sub(arr, first, sprout::size(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, Container>::type sub( Container const& arr ) { return sprout::sub(arr, sprout::begin(arr), sprout::end(arr)); } // // csub // template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits >::const_iterator first, typename sprout::fixed_container_traits >::const_iterator last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits >::difference_type first, typename sprout::fixed_container_traits >::difference_type last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits >::const_iterator first ) { return sprout::csub(arr, first, sprout::end(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits >::difference_type first ) { return sprout::csub(arr, first, sprout::size(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr ) { return sprout::csub(arr, sprout::begin(arr), sprout::end(arr)); } // // csub // template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits::const_iterator first, typename sprout::fixed_container_traits::const_iterator last ) { return sprout::sub_array(arr.get_array(), first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits::difference_type first, typename sprout::fixed_container_traits::difference_type last ) { return sprout::sub_array(arr.get_array(), sprout::begin(arr) + first, sprout::begin(arr) + last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits::const_iterator first ) { return sprout::csub(arr, first, sprout::end(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr, typename sprout::fixed_container_traits::difference_type first ) { return sprout::csub(arr, first, sprout::size(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type csub( Container const& arr ) { return sprout::csub(arr, sprout::begin(arr), sprout::end(arr)); } // // sub_copy // template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::const_iterator first, typename sprout::fixed_container_traits::const_iterator last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::difference_type first, typename sprout::fixed_container_traits::difference_type last ) { return sprout::sub_array(arr, first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::const_iterator first ) { return sprout::sub_copy(arr, first, sprout::end(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::difference_type first ) { return sprout::sub_copy(arr, first, sprout::size(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr ) { return sprout::sub_copy(arr, sprout::begin(arr), sprout::end(arr)); } // // sub_copy // template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::const_iterator first, typename sprout::fixed_container_traits::const_iterator last ) { return sprout::sub_array(arr.get_array(), first, last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::difference_type first, typename sprout::fixed_container_traits::difference_type last ) { return sprout::sub_array(arr.get_array(), sprout::begin(arr) + first, sprout::begin(arr) + last); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::const_iterator first ) { return sprout::sub_copy(arr, first, sprout::end(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr, typename sprout::fixed_container_traits::difference_type first ) { return sprout::sub_copy(arr, first, sprout::size(arr)); } template SPROUT_CONSTEXPR inline typename std::enable_if::value, sprout::sub_array >::type sub_copy( Container const& arr ) { return sprout::sub_copy(arr, sprout::begin(arr), sprout::end(arr)); } } // namespace sprout namespace std { // // tuple_size // template struct tuple_size > { public: SPROUT_STATIC_CONSTEXPR std::size_t value = std::tuple_size< typename std::remove_const< typename std::remove_reference::type >::type >::value; }; // // tuple_element // template struct tuple_element > { public: typedef typename std::tuple_element< I, typename std::remove_const< typename std::remove_reference::type >::type >::type type; }; // // get // template T& get(sprout::sub_array& arr) SPROUT_NOEXCEPT { static_assert(I < sprout::fixed_container_traits >::fixed_size, "tuple_element<>: index out of range"); return *(sprout::fixed_begin(arr) + I); } template SPROUT_CONSTEXPR T const& get(sprout::sub_array const& arr) SPROUT_NOEXCEPT { static_assert(I < sprout::fixed_container_traits >::fixed_size, "tuple_element<>: index out of range"); return *(sprout::fixed_begin(arr) + I); } template T&& get(sprout::sub_array&& arr) SPROUT_NOEXCEPT { return std::move(get(arr)); } } // namespace std #endif // #ifndef SPROUT_SUB_ARRAY_HPP