From 6ae26b7470d70e1bcf8637b7363844910c8fc1b6 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Thu, 6 Oct 2011 21:45:01 +0900 Subject: [PATCH] =?UTF-8?q?null=5Farray=20=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sprout/array.hpp | 4 +- sprout/fixed_container/remake_clone.hpp | 9 +- sprout/iterator/value_iterator.hpp | 195 +++++++++++++++ sprout/null_array.hpp | 300 ++++++++++++++++++++++++ sprout/random/random_iterator.hpp | 2 +- sprout/sub_array.hpp | 21 +- sprout/utility/value_holder.hpp | 160 +++++++++++++ 7 files changed, 680 insertions(+), 11 deletions(-) create mode 100644 sprout/iterator/value_iterator.hpp create mode 100644 sprout/null_array.hpp create mode 100644 sprout/utility/value_holder.hpp diff --git a/sprout/array.hpp b/sprout/array.hpp index 345240ab..8a6f4b3b 100644 --- a/sprout/array.hpp +++ b/sprout/array.hpp @@ -131,12 +131,12 @@ namespace sprout { void swap(array& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::swap(std::declval(), std::declval()))) { std::swap_ranges(other.begin(), other.end(), begin()); } - template + template array& operator=(array const& rhs) { std::copy(rhs.begin(), rhs.end(), begin()); return *this; } - template + template array& operator=(array&& rhs) { std::move(rhs.begin(), rhs.end(), begin()); return *this; diff --git a/sprout/fixed_container/remake_clone.hpp b/sprout/fixed_container/remake_clone.hpp index 312851c7..14a96dc6 100644 --- a/sprout/fixed_container/remake_clone.hpp +++ b/sprout/fixed_container/remake_clone.hpp @@ -18,8 +18,13 @@ namespace sprout { return sprout::remake_clone_functor().template operator()(other, size, args...); } template - SPROUT_CONSTEXPR inline typename sprout::fixed_container_traits::clone_type remake_clone(Other const& other, Args const&... args) { - return sprout::remake_clone_functor().template operator()(other, args...); + SPROUT_CONSTEXPR inline typename sprout::fixed_container_traits::clone_type remake_clone( + Other const& other, + typename sprout::fixed_container_traits::difference_type size, + Args const&... args + ) + { + return sprout::remake_clone_functor().template operator()(other, size, args...); } // diff --git a/sprout/iterator/value_iterator.hpp b/sprout/iterator/value_iterator.hpp new file mode 100644 index 00000000..e84e341e --- /dev/null +++ b/sprout/iterator/value_iterator.hpp @@ -0,0 +1,195 @@ +#ifndef SPROUT_ITERATOR_VALUE_ITERATOR_HPP +#define SPROUT_ITERATOR_VALUE_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // value_iterator + // + template + class value_iterator + : public std::iterator< + std::random_access_iterator_tag, + typename sprout::value_holder::value_type, + std::ptrdiff_t, + typename sprout::value_holder::mutable_or_const_pointer, + typename sprout::value_holder::mutable_or_const_reference + > + { + public: + typedef T type; + private: + typedef std::iterator< + std::random_access_iterator_tag, + typename sprout::value_holder::value_type, + std::ptrdiff_t, + typename sprout::value_holder::mutable_or_const_pointer, + typename sprout::value_holder::mutable_or_const_reference + > base_type; + public: + typedef typename base_type::iterator_category iterator_category; + typedef typename base_type::value_type value_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::reference reference; + private: + sprout::value_holder holder_; + difference_type count_; + private: + SPROUT_CONSTEXPR value_iterator(sprout::value_holder const& r, std::size_t count) + : holder_(r) + , count_(count) + {} + public: + SPROUT_CONSTEXPR value_iterator() + : holder_() + , count_() + {} + value_iterator(value_iterator const&) = default; + SPROUT_CONSTEXPR explicit value_iterator(typename sprout::value_holder::param_type p, std::size_t count = -1) + : holder_(p) + , count_(count) + {} + SPROUT_CONSTEXPR value_iterator next() const { + return value_iterator(holder_, count_ != 0 ? count_ - 1 : count_); + } + SPROUT_CONSTEXPR value_iterator prev() const { + return value_iterator(holder_, count_ != 0 ? count_ + 1 : count_); + } + void swap(value_iterator& other) { + using std::swap; + swap(holder_, other.holder_); + swap(count_, other.count_); + } + friend SPROUT_CONSTEXPR bool operator==(value_iterator const& lhs, value_iterator const& rhs) { + return lhs.count_ == rhs.count_ && (lhs.count_ == 0 || lhs.holder_.get() == rhs.holder_.get()); + } + friend SPROUT_CONSTEXPR bool operator!=(value_iterator const& lhs, value_iterator const& rhs) { + return !(lhs == rhs); + } + friend bool operator<(value_iterator const& lhs, value_iterator const& rhs) { + return lhs.count_ > rhs.count_; + } + friend bool operator>(value_iterator const& lhs, value_iterator const& rhs) { + return rhs < lhs; + } + friend bool operator<=(value_iterator const& lhs, value_iterator const& rhs) { + return !(rhs < lhs); + } + friend bool operator>=(value_iterator const& lhs, value_iterator const& rhs) { + return !(lhs < rhs); + } + SPROUT_CONSTEXPR reference operator*() const { + return count_ != 0 + ? holder_.get() + : (throw "assert(count_ != 0)", holder_.get()) + ; + } + SPROUT_CONSTEXPR pointer operator->() const { + return count_ != 0 + ? holder_.get_pointer() + : throw "assert(count_ != 0)" + ; + } + value_iterator& operator++() { + value_iterator temp(next()); + temp.swap(*this); + return *this; + } + value_iterator operator++(int) { + value_iterator result(*this); + ++*this; + return result; + } + value_iterator& operator--() { + value_iterator temp(prev()); + temp.swap(*this); + return *this; + } + value_iterator operator--(int) { + value_iterator result(*this); + --*this; + return result; + } + SPROUT_CONSTEXPR value_iterator operator+(difference_type n) const { + return value_iterator(holder_, count_ - n); + } + SPROUT_CONSTEXPR value_iterator operator-(difference_type n) const { + return value_iterator(holder_, count_ + n); + } + value_iterator& operator+=(difference_type n) { + value_iterator temp(holder_, count_ - n); + temp.swap(this); + return this; + } + value_iterator& operator-=(difference_type n) { + value_iterator temp(holder_, count_ + n); + temp.swap(this); + return this; + } + SPROUT_CONSTEXPR reference operator[](difference_type n) const { + return holder_.get(); + } + friend difference_type operator-(value_iterator const& lhs, value_iterator const& rhs) { + return rhs.count_ - lhs.count_; + } + friend SPROUT_CONSTEXPR value_iterator operator+(difference_type n, value_iterator const& it) { + return it + n; + } + }; + + // + // swap + // + template + void swap(sprout::value_iterator& lhs, sprout::value_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { + lhs.swap(rhs); + } + + // + // next + // + template + SPROUT_CONSTEXPR sprout::value_iterator next( + sprout::value_iterator const& it + ) + { + return it.next(); + } + template + SPROUT_CONSTEXPR sprout::value_iterator next( + sprout::value_iterator const& it, + typename sprout::value_iterator::difference_type n + ) + { + return it + n; + } + + // + // prev + // + template + SPROUT_CONSTEXPR sprout::value_iterator prev( + sprout::value_iterator const& it + ) + { + return it.prev(); + } + template + SPROUT_CONSTEXPR sprout::value_iterator prev( + sprout::value_iterator const& it, + typename sprout::value_iterator::difference_type n + ) + { + return it - n; + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_VALUE_ITERATOR_HPP diff --git a/sprout/null_array.hpp b/sprout/null_array.hpp new file mode 100644 index 00000000..cfc54da4 --- /dev/null +++ b/sprout/null_array.hpp @@ -0,0 +1,300 @@ +#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; + SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { + return static_size; + } + SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { + return static_size == 0; + } + SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { + return size(); + } + void rangecheck(size_type i) const { + if (i >= size()) { + throw std::out_of_range("null_array<>: index out of range"); + } + } + iterator begin() { + return iterator(elem, static_size); + } + SPROUT_CONSTEXPR const_iterator begin() const { + return const_iterator(elem, static_size); + } + SPROUT_CONSTEXPR const_iterator cbegin() const SPROUT_NOEXCEPT { + return const_iterator(elem, static_size); + } + iterator end() SPROUT_NOEXCEPT { + return iterator(); + } + SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT { + return const_iterator(); + } + SPROUT_CONSTEXPR const_iterator cend() 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()); + } + SPROUT_CONSTEXPR const_reverse_iterator crbegin() 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_reverse_iterator crend() const SPROUT_NOEXCEPT { + return const_reverse_iterator(begin()); + } + 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; + } + void swap(null_array& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::swap(std::declval(), std::declval()))) { + using std::swap; + swap(elem, other.elem); + } + }; + 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 diff --git a/sprout/random/random_iterator.hpp b/sprout/random/random_iterator.hpp index 4ac68dea..766bf102 100644 --- a/sprout/random/random_iterator.hpp +++ b/sprout/random/random_iterator.hpp @@ -123,7 +123,7 @@ namespace sprout { ; } SPROUT_CONSTEXPR pointer operator->() const { - return count_ > 0 + return count_ != 0 ? &random_.result() : throw "assert(count_ != 0)" ; diff --git a/sprout/sub_array.hpp b/sprout/sub_array.hpp index e1504f48..cf30f541 100644 --- a/sprout/sub_array.hpp +++ b/sprout/sub_array.hpp @@ -926,18 +926,27 @@ namespace std { // // get // - template - T& get(sprout::sub_array& arr) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(arr), I))) { + template + typename sprout::fixed_container_traits >::value_type& get( + sprout::sub_array& arr + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(arr), I))) + { static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); return *sprout::next(sprout::fixed_begin(arr), I); } - template - SPROUT_CONSTEXPR T const& get(sprout::sub_array const& arr) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(arr), I))) { + template + SPROUT_CONSTEXPR typename sprout::fixed_container_traits >::value_type const& get( + sprout::sub_array const& arr + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(*sprout::next(sprout::fixed_begin(arr), I))) + { static_assert(I < sprout::fixed_container_traits >::fixed_size, "get: index out of range"); return *sprout::next(sprout::fixed_begin(arr), I); } - template - T&& get(sprout::sub_array&& arr) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::move(std::get(arr)))) { + template + typename sprout::fixed_container_traits >::value_type&& get( + sprout::sub_array&& arr + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::move(std::get(arr)))) + { return std::move(std::get(arr)); } } // namespace std diff --git a/sprout/utility/value_holder.hpp b/sprout/utility/value_holder.hpp new file mode 100644 index 00000000..5dd63d91 --- /dev/null +++ b/sprout/utility/value_holder.hpp @@ -0,0 +1,160 @@ +#ifndef SPROUT_UTILITY_VALUE_HOLDER_HPP +#define SPROUT_UTILITY_VALUE_HOLDER_HPP + +#include + +namespace sprout { + namespace detail { + template + struct holder_helper { + public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T const& mutable_or_const_reference; + typedef T* pointer; + typedef T const* const_pointer; + typedef T const* mutable_or_const_pointer; + typedef T const& param_type; + typedef T holder_type; + public: + static SPROUT_CONSTEXPR holder_type const& hold(param_type p) { + return p; + } + static SPROUT_CONSTEXPR reference ref(holder_type& r) { + return r; + } + static SPROUT_CONSTEXPR const_reference ref(holder_type const& r) { + return r; + } + static SPROUT_CONSTEXPR pointer ptr(holder_type& r) { + return &r; + } + static SPROUT_CONSTEXPR const_pointer ptr(holder_type const& r) { + return &r; + } + }; + template + struct holder_helper { + public: + typedef T value_type; + typedef T const& reference; + typedef T const& const_reference; + typedef T const& mutable_or_const_reference; + typedef T const* pointer; + typedef T const* const_pointer; + typedef T const* mutable_or_const_pointer; + typedef T const& param_type; + typedef T holder_type; + public: + static SPROUT_CONSTEXPR holder_type const& hold(param_type p) { + return &p; + } + static SPROUT_CONSTEXPR reference ref(holder_type& r) { + return *r; + } + static SPROUT_CONSTEXPR const_reference ref(holder_type const& r) { + return *r; + } + static SPROUT_CONSTEXPR pointer ptr(holder_type& r) { + return &r; + } + static SPROUT_CONSTEXPR const_pointer ptr(holder_type const& r) { + return &r; + } + }; + template + struct holder_helper { + public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T& mutable_or_const_reference; + typedef T* pointer; + typedef T const* const_pointer; + typedef T* mutable_or_const_pointer; + typedef T& param_type; + typedef T* holder_type; + public: + static SPROUT_CONSTEXPR holder_type hold(param_type p) { + return &p; + } + static SPROUT_CONSTEXPR reference ref(holder_type r) { + return *r; + } + static SPROUT_CONSTEXPR pointer ptr(holder_type r) { + return r; + } + }; + template + struct holder_helper { + public: + typedef T value_type; + typedef T const& reference; + typedef T const& const_reference; + typedef T const& mutable_or_const_reference; + typedef T const* pointer; + typedef T const* const_pointer; + typedef T const* mutable_or_const_pointer; + typedef T const& param_type; + typedef T const* holder_type; + public: + static SPROUT_CONSTEXPR holder_type hold(param_type p) { + return &p; + } + static SPROUT_CONSTEXPR reference ref(holder_type r) { + return *r; + } + static SPROUT_CONSTEXPR pointer ptr(holder_type r) { + return r; + } + }; + } // namespace detail + // + // value_holder + // + template + class value_holder { + public: + typedef T type; + private: + typedef sprout::detail::holder_helper helper_type; + typedef typename helper_type::holder_type holder_type; + public: + typedef typename helper_type::value_type value_type; + typedef typename helper_type::reference reference; + typedef typename helper_type::const_reference const_reference; + typedef typename helper_type::mutable_or_const_reference mutable_or_const_reference; + typedef typename helper_type::pointer pointer; + typedef typename helper_type::const_pointer const_pointer; + typedef typename helper_type::mutable_or_const_pointer mutable_or_const_pointer; + typedef typename helper_type::param_type param_type; + private: + holder_type holder_; + public: + value_holder() = default; + SPROUT_CONSTEXPR explicit value_holder(param_type p) + : holder_(helper_type::hold(p)) + {} + operator reference() { + return helper_type::ref(holder_); + } + SPROUT_CONSTEXPR operator const_reference() const { + return helper_type::ref(holder_); + } + reference get() { + return helper_type::ref(holder_); + } + SPROUT_CONSTEXPR mutable_or_const_reference get() const { + return helper_type::ref(holder_); + } + pointer get_pointer() { + return helper_type::ptr(holder_); + } + SPROUT_CONSTEXPR mutable_or_const_pointer get_pointer() const { + return helper_type::ptr(holder_); + } + }; +} // namespace sprout + +#endif // #ifndef SPROUT_UTILITY_VALUE_HOLDER_HPP