#ifndef SPROUT_NULL_ARRAY_HPP #define SPROUT_NULL_ARRAY_HPP #include #include #include #include #include #include #include #include namespace sprout { // // null_array // template class null_array { public: typedef Container container_type; typedef null_array fixed_container_type; typedef container_type internal_type; typedef typename sprout::fixed_container_traits::clone_type clone_type; typedef typename sprout::fixed_container_traits::value_type value_type; typedef typename sprout::fixed_container_traits::reference reference; typedef typename sprout::fixed_container_traits::const_reference const_reference; typedef typename sprout::value_iterator iterator; typedef typename sprout::value_iterator const_iterator; typedef typename sprout::fixed_container_traits::size_type size_type; typedef typename sprout::fixed_container_traits::difference_type difference_type; typedef typename sprout::fixed_container_traits::pointer pointer; typedef typename sprout::fixed_container_traits::const_pointer const_pointer; typedef typename sprout::reverse_iterator reverse_iterator; typedef typename sprout::reverse_iterator const_reverse_iterator; public: SPROUT_STATIC_CONSTEXPR size_type static_size = sprout::fixed_container_traits::fixed_size; SPROUT_STATIC_CONSTEXPR size_type fixed_size = static_size; public: value_type elem; public: null_array() = default; void swap(null_array& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::swap(std::declval(), std::declval()))) { using std::swap; swap(elem, other.elem); } // iterators: iterator begin() { return iterator(elem, static_size); } SPROUT_CONSTEXPR const_iterator begin() const { return const_iterator(elem, static_size); } iterator end() SPROUT_NOEXCEPT { return iterator(); } SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT { return const_iterator(); } reverse_iterator rbegin() SPROUT_NOEXCEPT { return reverse_iterator(end()); } SPROUT_CONSTEXPR const_reverse_iterator rbegin() const SPROUT_NOEXCEPT { return const_reverse_iterator(end()); } reverse_iterator rend() SPROUT_NOEXCEPT { return reverse_iterator(begin()); } SPROUT_CONSTEXPR const_reverse_iterator rend() const SPROUT_NOEXCEPT { return const_reverse_iterator(begin()); } SPROUT_CONSTEXPR const_iterator cbegin() const SPROUT_NOEXCEPT { return const_iterator(elem, static_size); } SPROUT_CONSTEXPR const_iterator cend() const SPROUT_NOEXCEPT { return const_iterator(); } SPROUT_CONSTEXPR const_reverse_iterator crbegin() const SPROUT_NOEXCEPT { return const_reverse_iterator(end()); } SPROUT_CONSTEXPR const_reverse_iterator crend() const SPROUT_NOEXCEPT { return const_reverse_iterator(begin()); } // capacity: SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { return static_size; } SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { return size(); } SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { return static_size == 0; } // element access: reference operator[](size_type i) { return elem; } SPROUT_CONSTEXPR const_reference operator[](size_type i) const { return elem; } reference at(size_type i) { rangecheck(i); return elem; } const_reference at(size_type i) const { rangecheck(i); return elem; } reference front() { return elem; } SPROUT_CONSTEXPR const_reference front() const { return elem; } reference back() { return elem; } SPROUT_CONSTEXPR const_reference back() const { return elem; } // others: void rangecheck(size_type i) const { if (i >= size()) { throw std::out_of_range("null_array<>: index out of range"); } } }; template SPROUT_CONSTEXPR typename sprout::null_array::size_type sprout::null_array::static_size; template SPROUT_CONSTEXPR typename sprout::null_array::size_type sprout::null_array::fixed_size; // // operator== // operator!= // operator< // operator> // operator<= // operator>= // template SPROUT_CONSTEXPR inline bool operator==(sprout::null_array const& lhs, sprout::null_array const& rhs) { return lhs.front() == rhs.front(); } template SPROUT_CONSTEXPR inline bool operator!=(sprout::null_array const& lhs, sprout::null_array const& rhs) { return !(lhs == rhs); } template SPROUT_CONSTEXPR inline bool operator<(sprout::null_array const& lhs, sprout::null_array const& rhs) { return lhs.front() < rhs.front(); } template SPROUT_CONSTEXPR inline bool operator>(sprout::null_array const& lhs, sprout::null_array const& rhs) { return rhs < lhs; } template SPROUT_CONSTEXPR inline bool operator<=(sprout::null_array const& lhs, sprout::null_array const& rhs) { return !(rhs < lhs); } template SPROUT_CONSTEXPR inline bool operator>=(sprout::null_array const& lhs, sprout::null_array const& rhs) { return !(lhs < rhs); } // // swap // template inline void swap(sprout::null_array& lhs, sprout::null_array& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // fixed_container_traits // template struct fixed_container_traits > : public sprout::detail::fixed_container_traits_base > { public: typedef typename sprout::null_array::fixed_container_type fixed_container_type; typedef typename sprout::null_array::internal_type internal_type; typedef typename sprout::null_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::null_array< typename sprout::rebind_fixed_size< typename sprout::fixed_container_traits >::internal_type >::template apply::type > type; }; }; // // clone_functor // template struct clone_functor > { private: typedef typename sprout::fixed_container_traits >::clone_type clone_type; public: clone_type operator()(sprout::null_array& cont) const { return clone_type(); } SPROUT_CONSTEXPR clone_type operator()(sprout::null_array const& cont) const { return clone_type(); } }; // // 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; public: template SPROUT_CONSTEXPR clone_type operator()(Args const&... args) const { return 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; public: template clone_type operator()( Other& other, typename sprout::fixed_container_traits >::difference_type size, Args const&... args ) const { return sprout::remake_clone(other, size, args...); } template SPROUT_CONSTEXPR clone_type operator()( Other const& other, typename sprout::fixed_container_traits >::difference_type size, Args const&... args ) const { return sprout::remake_clone(other, size, args...); } }; } // namespace sprout namespace std { // // tuple_size // template struct tuple_size > { public: typedef std::integral_constant >::fixed_size> type; SPROUT_STATIC_CONSTEXPR std::size_t value = type::value; }; // // tuple_element // template struct tuple_element > { public: static_assert(I < sprout::fixed_container_traits >::fixed_size, "tuple_element<>: index out of range"); typedef typename sprout::fixed_container_traits >::value_type type; }; // // get // template typename sprout::fixed_container_traits >::value_type& get( sprout::null_array& arr ) SPROUT_NOEXCEPT { static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); return arr[I]; } template SPROUT_CONSTEXPR typename sprout::fixed_container_traits >::value_type const& get( sprout::null_array const& arr ) SPROUT_NOEXCEPT { static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); return arr[I]; } template typename sprout::fixed_container_traits >::value_type&& get( sprout::null_array&& arr ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::move(std::get(arr)))) { return std::move(std::get(arr)); } } // namespace std #endif // #ifndef SPROUT_NULL_ARRAY_HPP