From e286c9bc6b05f58777c7e6b850c86b3681e639ed Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 17 Nov 2012 01:59:56 +0900 Subject: [PATCH] add adaptors::jointed --- sprout/algorithm/string/join.hpp | 2 +- sprout/iterator.hpp | 2 +- sprout/iterator/adaptor.hpp | 1 + sprout/iterator/joint_iterator.hpp | 364 ++++++++++++++++++++ sprout/iterator/traits.hpp | 90 +++++ sprout/iterator/transform_iterator.hpp | 12 +- sprout/iterator/type_traits.hpp | 8 + sprout/iterator/type_traits/common.hpp | 164 +++++++++ sprout/iterator/type_traits/is_iterator.hpp | 97 ++++++ sprout/random.hpp | 19 +- sprout/random/distribution.hpp | 14 + sprout/random/engine.hpp | 15 + sprout/range/adaptor.hpp | 1 + sprout/range/adaptor/jointed.hpp | 146 ++++++++ 14 files changed, 907 insertions(+), 28 deletions(-) create mode 100644 sprout/iterator/joint_iterator.hpp create mode 100644 sprout/iterator/type_traits.hpp create mode 100644 sprout/iterator/type_traits/common.hpp create mode 100644 sprout/iterator/type_traits/is_iterator.hpp create mode 100644 sprout/random/distribution.hpp create mode 100644 sprout/random/engine.hpp create mode 100644 sprout/range/adaptor/jointed.hpp diff --git a/sprout/algorithm/string/join.hpp b/sprout/algorithm/string/join.hpp index ceba474f..b51bb47b 100644 --- a/sprout/algorithm/string/join.hpp +++ b/sprout/algorithm/string/join.hpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sprout/iterator.hpp b/sprout/iterator.hpp index b01316d3..47dd921f 100644 --- a/sprout/iterator.hpp +++ b/sprout/iterator.hpp @@ -2,7 +2,7 @@ #define SPROUT_ITERATOR_HPP #include -#include +#include #include #include diff --git a/sprout/iterator/adaptor.hpp b/sprout/iterator/adaptor.hpp index 3b2d6b70..2a91aa8a 100644 --- a/sprout/iterator/adaptor.hpp +++ b/sprout/iterator/adaptor.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/sprout/iterator/joint_iterator.hpp b/sprout/iterator/joint_iterator.hpp new file mode 100644 index 00000000..802a5bd3 --- /dev/null +++ b/sprout/iterator/joint_iterator.hpp @@ -0,0 +1,364 @@ +#ifndef SPROUT_ITERATOR_JOINT_ITERATOR_HPP +#define SPROUT_ITERATOR_JOINT_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT + +namespace sprout { + // + // joint_iterator + // + template + class joint_iterator + : public std::iterator< + typename sprout::common_iterator_category::type, + typename sprout::common_iterator_value_type::type, + typename sprout::common_iterator_difference_type::type, + typename sprout::common_iterator_pointer::type, + typename sprout::common_iterator_reference::type + > + { + public: + typedef LIterator iterator_type; + typedef RIterator iterator2_type; + typedef typename sprout::common_iterator_category::type iterator_category; + typedef typename sprout::common_iterator_value_type::type value_type; + typedef typename sprout::common_iterator_difference_type::type difference_type; + typedef typename sprout::common_iterator_pointer::type pointer; + typedef typename sprout::common_iterator_reference::type reference; + protected: + iterator_type current1; + iterator_type last1; + iterator2_type first2; + iterator2_type current2; + private: + SPROUT_CONSTEXPR joint_iterator advance_impl_posite(difference_type n, difference_type d) const { + return n > d ? joint_iterator(last1, last1, first2, sprout::next(current2, n - d)) + : joint_iterator(sprout::next(current1, n), last1, first2, current2) + ; + } + SPROUT_CONSTEXPR joint_iterator advance_impl_negate(difference_type n, difference_type d) const { + return !(n > d) ? joint_iterator(sprout::next(current1, n - d), last1, first2, first2) + : joint_iterator(current1, last1, first2, sprout::next(current2, n)) + ; + } + SPROUT_CONSTEXPR joint_iterator advance_impl(difference_type n) const { + return n >= 0 + ? is_in_left() + ? advance_impl_posite(n, NS_SSCRISK_CEL_OR_SPROUT::distance(current1, last1)) + : joint_iterator(current1, last1, first2, sprout::next(current2, n)) + : first2 == current2 + ? joint_iterator(sprout::next(current1, n), last1, first2, current2) + : advance_impl_negate(n, -NS_SSCRISK_CEL_OR_SPROUT::distance(first2, current2)) + ; + } + public: + joint_iterator() = default; + joint_iterator(joint_iterator const&) = default; + SPROUT_CONSTEXPR joint_iterator(iterator_type it1, iterator_type last1, iterator2_type first2, iterator2_type it2) + : current1(it1) + , last1(last1) + , first2(first2) + , current2(it2) + {} + template + SPROUT_CONSTEXPR joint_iterator(joint_iterator const& it) + : current1(it.base()) + , last1(it.left_end()) + , first2(it.right_begin()) + , current2(it.base2()) + {} + template + joint_iterator& operator=(joint_iterator const& it) { + joint_iterator temp(it); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR iterator_type base() const { + return current1; + } + SPROUT_CONSTEXPR iterator_type left_end() const { + return last1; + } + SPROUT_CONSTEXPR iterator2_type right_begin() const { + return first2; + } + SPROUT_CONSTEXPR iterator2_type base2() const { + return current2; + } + SPROUT_CONSTEXPR bool is_in_left() const { + return current1 != last1; + } + SPROUT_CONSTEXPR reference operator*() const { + return is_in_left() ? *current1 : *current2; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &*(*this); + } + joint_iterator& operator++() { + if (is_in_left()) { + ++current1; + } else { + ++current2; + } + return *this; + } + joint_iterator operator++(int) { + joint_iterator result(*this); + if (is_in_left()) { + ++current1; + } else { + ++current2; + } + return result; + } + joint_iterator& operator--() { + if (first2 == current2) { + --current1; + } else { + --current2; + } + return *this; + } + joint_iterator operator--(int) { + joint_iterator temp(*this); + if (first2 == current2) { + --current1; + } else { + --current2; + } + return temp; + } + SPROUT_CONSTEXPR joint_iterator operator+(difference_type n) const { + return advance_impl(n); + } + SPROUT_CONSTEXPR joint_iterator operator-(difference_type n) const { + return advance_impl(-n); + } + joint_iterator& operator+=(difference_type n) { + joint_iterator temp(*this + n); + temp.swap(*this); + return *this; + } + joint_iterator& operator-=(difference_type n) { + joint_iterator temp(*this - n); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR reference operator[](difference_type n) const { + return *(*this + n); + } + SPROUT_CONSTEXPR joint_iterator next() const { + return is_in_left() ? joint_iterator(sprout::next(current1), last1, first2, current2) + : joint_iterator(current1, last1, first2, sprout::next(current2)) + ; + } + SPROUT_CONSTEXPR joint_iterator prev() const { + return first2 == current2 ? joint_iterator(sprout::prev(current1), last1, first2, current2) + : joint_iterator(current1, last1, first2, sprout::prev(current2)) + ; + } + void swap(joint_iterator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(sprout::swap(current1, other.current1)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(last1, other.last1)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(first2, other.first2)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(current2, other.current2)) + ) + { + sprout::swap(current1, other.current1); + sprout::swap(last1, other.last1); + sprout::swap(first2, other.first2); + sprout::swap(current2, other.current2); + } + }; + + template< + typename LIterator1, typename RIterator1, + typename LIterator2, typename RIterator2 + > + inline SPROUT_CONSTEXPR bool operator==( + sprout::joint_iterator const& lhs, + sprout::joint_iterator const& rhs + ) + { + return lhs.base() == rhs.base() && lhs.base2() == rhs.base2(); + } + template< + typename LIterator1, typename RIterator1, + typename LIterator2, typename RIterator2 + > + inline SPROUT_CONSTEXPR bool operator!=( + sprout::joint_iterator const& lhs, + sprout::joint_iterator const& rhs + ) + { + return !(lhs == rhs); + } + template< + typename LIterator1, typename RIterator1, + typename LIterator2, typename RIterator2 + > + inline SPROUT_CONSTEXPR bool operator<( + sprout::joint_iterator const& lhs, + sprout::joint_iterator const& rhs + ) + { + return lhs.is_in_left() && rhs.is_in_left() ? lhs.base() < rhs.base() + : !lhs.is_in_left() && !rhs.is_in_left() ? lhs.base2() < rhs.base2() + : lhs.is_in_left() + ; + } + template< + typename LIterator1, typename RIterator1, + typename LIterator2, typename RIterator2 + > + inline SPROUT_CONSTEXPR bool operator>( + sprout::joint_iterator const& lhs, + sprout::joint_iterator const& rhs + ) + { + return rhs < lhs; + } + template< + typename LIterator1, typename RIterator1, + typename LIterator2, typename RIterator2 + > + inline SPROUT_CONSTEXPR bool operator<=( + sprout::joint_iterator const& lhs, + sprout::joint_iterator const& rhs + ) + { + return !(rhs < lhs); + } + template< + typename LIterator1, typename RIterator1, + typename LIterator2, typename RIterator2 + > + inline SPROUT_CONSTEXPR bool operator>=( + sprout::joint_iterator const& lhs, + sprout::joint_iterator const& rhs + ) + { + return !(lhs < rhs); + } + template< + typename LIterator1, typename RIterator1, + typename LIterator2, typename RIterator2 + > + inline SPROUT_CONSTEXPR typename std::common_type< + typename sprout::joint_iterator::difference_type, + typename sprout::joint_iterator::difference_type + >::type + operator-( + sprout::joint_iterator const& lhs, + sprout::joint_iterator const& rhs + ) + { + return lhs.is_in_left() && rhs.is_in_left() ? rhs.base() - lhs.base() + : !lhs.is_in_left() && !rhs.is_in_left() ? rhs.base2() - lhs.base2() + : lhs.is_in_left() ? (lhs.left_end() - lhs.base()) + (rhs.base2() - rhs.right_begin()) + : (lhs.base2() - lhs.right_begin()) + (rhs.left_end() - rhs.base()) + ; + } + template + inline SPROUT_CONSTEXPR sprout::joint_iterator operator+( + typename sprout::joint_iterator::difference_type n, + sprout::joint_iterator const& it + ) + { + return it + n; + } + + // + // make_joint_iterator + // + template + inline SPROUT_CONSTEXPR sprout::joint_iterator + make_joint_iterator(LIterator it1, LIterator last1, RIterator first2, RIterator it2) { + return sprout::joint_iterator(it1, last1, first2, it2); + } + template + inline SPROUT_CONSTEXPR sprout::joint_iterator + make_joint_iterator(LIterator it1, LIterator last1, RIterator first2) { + return sprout::joint_iterator(it1, last1, first2, first2); + } + template + inline SPROUT_CONSTEXPR sprout::joint_iterator + make_joint_iterator(LIterator last1, RIterator first2, RIterator it2) { + return sprout::joint_iterator(last1, last1, first2, it2); + } + + // + // swap + // + template + inline void + swap( + sprout::joint_iterator& lhs, + sprout::joint_iterator& rhs + ) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // iterator_distance + // + template + inline SPROUT_CONSTEXPR typename std::iterator_traits >::difference_type + iterator_distance( + sprout::joint_iterator first, + sprout::joint_iterator last + ) + { + return last - first; + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::joint_iterator + iterator_next(sprout::joint_iterator const& it) { + return it.next(); + } + template + inline SPROUT_CONSTEXPR sprout::joint_iterator + iterator_next( + sprout::joint_iterator const& it, + typename sprout::joint_iterator::difference_type n + ) + { + return it + n; + } + + // + // iterator_prev + // + template + inline SPROUT_CONSTEXPR sprout::joint_iterator + iterator_prev(sprout::joint_iterator const& it) { + return it.prev(); + } + template + inline SPROUT_CONSTEXPR sprout::joint_iterator + iterator_prev( + sprout::joint_iterator const& it, + typename sprout::joint_iterator::difference_type n + ) + { + return it - n; + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_JOINT_ITERATOR_HPP diff --git a/sprout/iterator/traits.hpp b/sprout/iterator/traits.hpp index 1707214b..ce473c08 100644 --- a/sprout/iterator/traits.hpp +++ b/sprout/iterator/traits.hpp @@ -153,6 +153,96 @@ namespace sprout { typename sprout::min_iterator_category::type > {}; + + // + // common_iterator_category + // + template + struct common_iterator_category + : public sprout::min_iterator_category< + typename std::iterator_traits::iterator_category... + > + {}; + + namespace detail { + template + struct common_iterator_reference_impl; + template + struct common_iterator_reference_impl { + public: + typedef T type; + }; + template + struct common_iterator_reference_impl + : public std::conditional< + std::is_reference::value && std::is_reference::value, + typename std::conditional< + std::is_convertible::value + && (std::is_same::type, typename std::decay::type>::value + || std::is_base_of::type, typename std::decay::type>::value + ) + , + U, + typename std::conditional< + std::is_convertible::value + && (std::is_same::type, typename std::decay::type>::value + || std::is_base_of::type, typename std::decay::type>::value + ) + , + T, + typename std::common_type::type, typename std::decay::type>::type + >::type + >::type, + typename std::common_type::type, typename std::decay::type>::type + > + {}; + template + struct common_iterator_reference_impl + : public sprout::detail::common_iterator_reference_impl< + typename sprout::detail::common_iterator_reference_impl::type, + Tail... + > + {}; + } // namespace detail + // + // common_iterator_reference + // + template + struct common_iterator_reference + : public sprout::detail::common_iterator_reference_impl< + typename std::iterator_traits::reference... + > + {}; + + // + // common_iterator_value_type + // + template + struct common_iterator_value_type + : public std::decay< + typename sprout::common_iterator_reference::type + > + {}; + + // + // common_iterator_pointer + // + template + struct common_iterator_pointer + : public std::add_pointer< + typename std::remove_reference::type>::type + > + {}; + + // + // common_iterator_difference_type + // + template + struct common_iterator_difference_type + : public std::common_type< + typename std::iterator_traits::difference_type... + > + {}; } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_TRAITS_HPP diff --git a/sprout/iterator/transform_iterator.hpp b/sprout/iterator/transform_iterator.hpp index f03abb45..b67d7a5b 100644 --- a/sprout/iterator/transform_iterator.hpp +++ b/sprout/iterator/transform_iterator.hpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include namespace sprout { @@ -18,10 +18,7 @@ namespace sprout { template class transform_iterator : public std::iterator< - typename sprout::min_iterator_category< - typename std::iterator_traits::iterator_category, - typename std::iterator_traits::iterator_category - >::type, + typename sprout::common_iterator_category::type, typename std::remove_reference< typename std::result_of< BinaryFunction ( @@ -51,10 +48,7 @@ namespace sprout { typedef BinaryFunction functor_type; typedef LIterator iterator_type; typedef RIterator iterator2_type; - typedef typename sprout::min_iterator_category< - typename std::iterator_traits::iterator_category, - typename std::iterator_traits::iterator_category - >::type iterator_category; + typedef typename sprout::common_iterator_category::type iterator_category; typedef typename std::result_of< BinaryFunction ( typename std::iterator_traits::reference, diff --git a/sprout/iterator/type_traits.hpp b/sprout/iterator/type_traits.hpp new file mode 100644 index 00000000..6e63ae1a --- /dev/null +++ b/sprout/iterator/type_traits.hpp @@ -0,0 +1,8 @@ +#ifndef SPROUT_ITERATOR_TYPE_TRAITS_HPP +#define SPROUT_ITERATOR_TYPE_TRAITS_HPP + +#include +#include +#include + +#endif // #ifndef SPROUT_ITERATOR_TYPE_TRAITS_HPP diff --git a/sprout/iterator/type_traits/common.hpp b/sprout/iterator/type_traits/common.hpp new file mode 100644 index 00000000..177f51d6 --- /dev/null +++ b/sprout/iterator/type_traits/common.hpp @@ -0,0 +1,164 @@ +#ifndef SPROUT_ITERATOR_TYPE_TRAITS_COMMON_HPP +#define SPROUT_ITERATOR_TYPE_TRAITS_COMMON_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + struct iterator_category_hierarchy_impl; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + template + struct iterator_category_hierarchy_impl + : public std::integral_constant + {}; + + template + struct iterator_category_hierarchy + : public sprout::detail::iterator_category_hierarchy_impl< + Category, + sprout::is_random_access_iterator_category::value, + sprout::is_bidirectional_iterator_category::value, + sprout::is_forward_iterator_category::value, + sprout::is_input_iterator_category::value || sprout::is_output_iterator_category::value + > + {}; + + template + struct iterator_category_less + : public std::integral_constant< + bool, + (sprout::detail::iterator_category_hierarchy::value < sprout::detail::iterator_category_hierarchy::value) + > + {}; + } // namespace detail + // + // min_iterator_category + // + template + struct min_iterator_category; + template + struct min_iterator_category + : public std::common_type + {}; + template + struct min_iterator_category + : public std::conditional< + sprout::detail::iterator_category_less::value, + Category1, Category2 + > + {}; + template + struct min_iterator_category + : public sprout::min_iterator_category< + Head, + typename sprout::min_iterator_category::type + > + {}; + + // + // common_iterator_category + // + template + struct common_iterator_category + : public sprout::min_iterator_category< + typename std::iterator_traits::iterator_category... + > + {}; + + namespace detail { + template + struct common_iterator_reference_impl; + template + struct common_iterator_reference_impl { + public: + typedef T type; + }; + template + struct common_iterator_reference_impl + : public std::conditional< + std::is_reference::value && std::is_reference::value, + typename std::conditional< + std::is_convertible::value + && (std::is_same::type, typename std::decay::type>::value + || std::is_base_of::type, typename std::decay::type>::value + ) + , + U, + typename std::conditional< + std::is_convertible::value + && (std::is_same::type, typename std::decay::type>::value + || std::is_base_of::type, typename std::decay::type>::value + ) + , + T, + typename std::common_type::type, typename std::decay::type>::type + >::type + >::type, + typename std::common_type::type, typename std::decay::type>::type + > + {}; + template + struct common_iterator_reference_impl + : public sprout::detail::common_iterator_reference_impl< + typename sprout::detail::common_iterator_reference_impl::type, + Tail... + > + {}; + } // namespace detail + // + // common_iterator_reference + // + template + struct common_iterator_reference + : public sprout::detail::common_iterator_reference_impl< + typename std::iterator_traits::reference... + > + {}; + + // + // common_iterator_value_type + // + template + struct common_iterator_value_type + : public std::decay< + typename sprout::common_iterator_reference::type + > + {}; + + // + // common_iterator_pointer + // + template + struct common_iterator_pointer + : public std::add_pointer< + typename std::remove_reference::type>::type + > + {}; + + // + // common_iterator_difference_type + // + template + struct common_iterator_difference_type + : public std::common_type< + typename std::iterator_traits::difference_type... + > + {}; +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_TYPE_TRAITS_COMMON_HPP diff --git a/sprout/iterator/type_traits/is_iterator.hpp b/sprout/iterator/type_traits/is_iterator.hpp new file mode 100644 index 00000000..e12498d1 --- /dev/null +++ b/sprout/iterator/type_traits/is_iterator.hpp @@ -0,0 +1,97 @@ +#ifndef SPROUT_ITERATOR_TYPE_TRAITS_IS_ITERATOR_HPP +#define SPROUT_ITERATOR_TYPE_TRAITS_IS_ITERATOR_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace detail { + // + // has_iterator_category + // + SPROUT_HAS_XXX_TYPE_DEF_LAZY(iterator_category); + } // namespace detail + // + // is_iterator + // + template + struct is_iterator + : public sprout::detail::has_iterator_category > + {}; + + // + // is_input_iterator_category + // + template + struct is_input_iterator_category + : public std::is_convertible + {}; + // + // is_output_iterator_category + // + template + struct is_output_iterator_category + : public std::is_convertible + {}; + // + // is_forward_iterator_category + // + template + struct is_forward_iterator_category + : public std::is_convertible + {}; + // + // is_bidirectional_iterator_category + // + template + struct is_bidirectional_iterator_category + : public std::is_convertible + {}; + // + // is_random_access_iterator_category + // + template + struct is_random_access_iterator_category + : public std::is_convertible + {}; + + // + // is_input_iterator + // + template + struct is_input_iterator + : public sprout::is_input_iterator_category::iterator_category> + {}; + // + // is_output_iterator + // + template + struct is_output_iterator + : public sprout::is_output_iterator_category::iterator_category> + {}; + // + // is_forward_iterator + // + template + struct is_forward_iterator + : public sprout::is_forward_iterator_category::iterator_category> + {}; + // + // is_bidirectional_iterator + // + template + struct is_bidirectional_iterator + : public sprout::is_bidirectional_iterator_category::iterator_category> + {}; + // + // is_random_access_iterator + // + template + struct is_random_access_iterator + : public sprout::is_random_access_iterator_category::iterator_category> + {}; +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_TYPE_TRAITS_IS_ITERATOR_HPP diff --git a/sprout/random.hpp b/sprout/random.hpp index cda73e2d..b7cf38b7 100644 --- a/sprout/random.hpp +++ b/sprout/random.hpp @@ -2,23 +2,8 @@ #define SPROUT_RANDOM_HPP #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include #include #include diff --git a/sprout/random/distribution.hpp b/sprout/random/distribution.hpp new file mode 100644 index 00000000..89f6d922 --- /dev/null +++ b/sprout/random/distribution.hpp @@ -0,0 +1,14 @@ +#ifndef SPROUT_RANDOM_DISTRIBUTION_HPP +#define SPROUT_RANDOM_DISTRIBUTION_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_RANDOM_DISTRIBUTION_HPP diff --git a/sprout/random/engine.hpp b/sprout/random/engine.hpp new file mode 100644 index 00000000..8918defa --- /dev/null +++ b/sprout/random/engine.hpp @@ -0,0 +1,15 @@ +#ifndef SPROUT_RANDOM_ENGINE_HPP +#define SPROUT_RANDOM_ENGINE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_RANDOM_ENGINE_HPP diff --git a/sprout/range/adaptor.hpp b/sprout/range/adaptor.hpp index 38da08e1..6e275f30 100644 --- a/sprout/range/adaptor.hpp +++ b/sprout/range/adaptor.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/sprout/range/adaptor/jointed.hpp b/sprout/range/adaptor/jointed.hpp new file mode 100644 index 00000000..fe55435e --- /dev/null +++ b/sprout/range/adaptor/jointed.hpp @@ -0,0 +1,146 @@ +#ifndef SPROUT_RANGE_ADAPTOR_JOINTED_HPP +#define SPROUT_RANGE_ADAPTOR_JOINTED_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace adaptors { + // + // jointed_range + // + template + class jointed_range + : public sprout::range::range_container< + sprout::joint_iterator< + typename sprout::container_traits::iterator, + typename sprout::container_traits::iterator + > + > + , public sprout::detail::container_nosy_static_size + , public sprout::detail::container_nosy_fixed_size + { + public: + typedef LRange range_type; + typedef RRange range2_type; + typedef sprout::range::range_container< + sprout::joint_iterator< + typename sprout::container_traits::iterator, + typename sprout::container_traits::iterator + > + > base_type; + typedef typename base_type::iterator iterator; + public: + jointed_range() = default; + jointed_range(jointed_range const&) = default; + SPROUT_CONSTEXPR jointed_range(range_type& range1, range2_type& range2) + : base_type( + iterator(sprout::begin(range1), sprout::end(range1), sprout::begin(range2), sprout::begin(range2)), + iterator(sprout::end(range1), sprout::end(range1), sprout::begin(range2), sprout::end(range2)) + ) + {} + }; + + // + // joint_holder + // + template + class joint_holder { + public: + typedef RRange range2_type; + private: + sprout::value_holder range_; + public: + joint_holder() = default; + joint_holder(joint_holder const&) = default; + explicit SPROUT_CONSTEXPR joint_holder(range2_type& range) + : range_(range) + {} + SPROUT_CONSTEXPR range2_type& range() const { + return range_; + } + }; + + // + // jointed_forwarder + // + class jointed_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::adaptors::joint_holder< + typename std::remove_reference::type>::type + > + operator()(RRange&& range) { + return sprout::adaptors::joint_holder< + typename std::remove_reference::type>::type + >( + sprout::lvalue_forward(range) + ); + } + }; + + // + // jointed + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::adaptors::jointed_forwarder jointed{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR sprout::adaptors::jointed_range< + typename std::remove_reference::type>::type, + RRange + > + operator|(LRange&& lhs, sprout::adaptors::joint_holder const& rhs) { + return sprout::adaptors::jointed_range< + typename std::remove_reference::type>::type, + RRange + >( + sprout::lvalue_forward(lhs), + rhs.range() + ); + } + } // namespace adaptors + + // + // 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::range::fixed::copy(sprout::forward(cont), sprout::pit()); + } + template + static SPROUT_CONSTEXPR copied_type make(Args&&... args) { + return sprout::make(sprout::forward(args)...); + } + template + static SPROUT_CONSTEXPR copied_type remake( + Cont&& cont, + typename sprout::container_traits >::difference_type size, + Args&&... args + ) + { + return sprout::remake(sprout::forward(cont), size, sprout::forward(args)...); + } + }; +} // namespace sprout + +#endif // #ifndef SPROUT_RANGE_ADAPTOR_JOINTED_HPP