From 6ae41ef6de887a8a4d2447674ec09b1047c3b39b Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Tue, 13 Aug 2013 01:55:26 +0900 Subject: [PATCH] fix algorithm: copy for InputIterator --- libs/algorithm/test/copy.cpp | 243 ++++++++++++++++++++++++++++++ sprout/algorithm/fixed/copy.hpp | 66 +++++++- sprout/iterator/adaptor.hpp | 1 + sprout/iterator/next_iterator.hpp | 137 +++++++++++++++++ 4 files changed, 443 insertions(+), 4 deletions(-) create mode 100644 sprout/iterator/next_iterator.hpp diff --git a/libs/algorithm/test/copy.cpp b/libs/algorithm/test/copy.cpp index c341d27c..d33cf77d 100644 --- a/libs/algorithm/test/copy.cpp +++ b/libs/algorithm/test/copy.cpp @@ -101,6 +101,249 @@ namespace testspr { array{{0, 0, 3, 4, 5, 6, 7, 8, 0, 0}} )); } + + // [2 .. 8) の範囲をコピー + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_input(sprout::begin(arr1) + 2), + testspr::reduct_input(sprout::begin(arr1) + 8), + arr2 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8, 0, 0, 0, 0}} + )); + } + // !!! +// { +// SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( +// testspr::reduct_input(sprout::begin(arr1) + 2), +// testspr::reduct_input(sprout::begin(arr1) + 8), +// arr2 +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// copied, +// array{{3, 4, 5, 6, 7, 8}} +// )); +// } + // [2 .. 8) の範囲をコピー + // 出力範囲をオーバーする場合 + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_input(sprout::begin(arr1) + 2), + testspr::reduct_input(sprout::begin(arr1) + 8), + arr3 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6}} + )); + } + // !!! +// { +// SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( +// testspr::reduct_input(sprout::begin(arr1) + 2), +// testspr::reduct_input(sprout::begin(arr1) + 8), +// arr3 +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// copied, +// array{{3, 4, 5, 6}} +// )); +// } + // [2 .. 8) の範囲をコピー + // 出力範囲の切り出し + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_input(sprout::begin(arr1) + 2), + testspr::reduct_input(sprout::begin(arr1) + 8), + sprout::sub(arr2, 2, 8) + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8}} + )); + TESTSPR_BOTH_ASSERT(testspr::equal( + sprout::get_internal(copied), + array{{0, 0, 3, 4, 5, 6, 7, 8, 0, 0}} + )); + } + // !!! +// { +// SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( +// testspr::reduct_input(sprout::begin(arr1) + 2), +// testspr::reduct_input(sprout::begin(arr1) + 8), +// sprout::sub(arr2, 2, 8) +// ); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// copied, +// array{{3, 4, 5, 6, 7, 8}} +// )); +// TESTSPR_BOTH_ASSERT(testspr::equal( +// sprout::get_internal(copied), +// array{{0, 0, 3, 4, 5, 6, 7, 8, 0, 0}} +// )); +// } + + // [2 .. 8) の範囲をコピー + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_forward(sprout::begin(arr1) + 2), + testspr::reduct_forward(sprout::begin(arr1) + 8), + arr2 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8, 0, 0, 0, 0}} + )); + } + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( + testspr::reduct_forward(sprout::begin(arr1) + 2), + testspr::reduct_forward(sprout::begin(arr1) + 8), + arr2 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8}} + )); + } + // [2 .. 8) の範囲をコピー + // 出力範囲をオーバーする場合 + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_forward(sprout::begin(arr1) + 2), + testspr::reduct_forward(sprout::begin(arr1) + 8), + arr3 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6}} + )); + } + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( + testspr::reduct_forward(sprout::begin(arr1) + 2), + testspr::reduct_forward(sprout::begin(arr1) + 8), + arr3 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6}} + )); + } + // [2 .. 8) の範囲をコピー + // 出力範囲の切り出し + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_forward(sprout::begin(arr1) + 2), + testspr::reduct_forward(sprout::begin(arr1) + 8), + sprout::sub(arr2, 2, 8) + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8}} + )); + TESTSPR_BOTH_ASSERT(testspr::equal( + sprout::get_internal(copied), + array{{0, 0, 3, 4, 5, 6, 7, 8, 0, 0}} + )); + } + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( + testspr::reduct_forward(sprout::begin(arr1) + 2), + testspr::reduct_forward(sprout::begin(arr1) + 8), + sprout::sub(arr2, 2, 8) + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8}} + )); + TESTSPR_BOTH_ASSERT(testspr::equal( + sprout::get_internal(copied), + array{{0, 0, 3, 4, 5, 6, 7, 8, 0, 0}} + )); + } + + // [2 .. 8) の範囲をコピー + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_random_access(sprout::begin(arr1) + 2), + testspr::reduct_random_access(sprout::begin(arr1) + 8), + arr2 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8, 0, 0, 0, 0}} + )); + } + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( + testspr::reduct_random_access(sprout::begin(arr1) + 2), + testspr::reduct_random_access(sprout::begin(arr1) + 8), + arr2 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8}} + )); + } + // [2 .. 8) の範囲をコピー + // 出力範囲をオーバーする場合 + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_random_access(sprout::begin(arr1) + 2), + testspr::reduct_random_access(sprout::begin(arr1) + 8), + arr3 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6}} + )); + } + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( + testspr::reduct_random_access(sprout::begin(arr1) + 2), + testspr::reduct_random_access(sprout::begin(arr1) + 8), + arr3 + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6}} + )); + } + // [2 .. 8) の範囲をコピー + // 出力範囲の切り出し + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::copy( + testspr::reduct_random_access(sprout::begin(arr1) + 2), + testspr::reduct_random_access(sprout::begin(arr1) + 8), + sprout::sub(arr2, 2, 8) + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8}} + )); + TESTSPR_BOTH_ASSERT(testspr::equal( + sprout::get_internal(copied), + array{{0, 0, 3, 4, 5, 6, 7, 8, 0, 0}} + )); + } + { + SPROUT_STATIC_CONSTEXPR auto copied = sprout::fit::copy( + testspr::reduct_random_access(sprout::begin(arr1) + 2), + testspr::reduct_random_access(sprout::begin(arr1) + 8), + sprout::sub(arr2, 2, 8) + ); + TESTSPR_BOTH_ASSERT(testspr::equal( + copied, + array{{3, 4, 5, 6, 7, 8}} + )); + TESTSPR_BOTH_ASSERT(testspr::equal( + sprout::get_internal(copied), + array{{0, 0, 3, 4, 5, 6, 7, 8, 0, 0}} + )); + } } } } // namespace testspr diff --git a/sprout/algorithm/fixed/copy.hpp b/sprout/algorithm/fixed/copy.hpp index dee70dde..28c3d599 100644 --- a/sprout/algorithm/fixed/copy.hpp +++ b/sprout/algorithm/fixed/copy.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -63,7 +64,7 @@ namespace sprout { sprout::container_traits::static_size == sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type - copy_impl( + copy_impl_fw( InputIterator, InputIterator, Result const& result, typename sprout::container_traits::size_type, Args const&... args @@ -76,14 +77,14 @@ namespace sprout { sprout::container_traits::static_size != sizeof...(Args), typename sprout::fixed::result_of::algorithm::type >::type - copy_impl( + copy_impl_fw( InputIterator first, InputIterator last, Result const& result, typename sprout::container_traits::size_type size, Args const&... args ) { return first != last && sizeof...(Args) < size - ? sprout::fixed::detail::copy_impl(sprout::next(first), last, result, size, args..., *first) + ? sprout::fixed::detail::copy_impl_fw(sprout::next(first), last, result, size, args..., *first) : sprout::detail::container_complate(result, args...) ; } @@ -91,10 +92,67 @@ namespace sprout { inline SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type copy( InputIterator first, InputIterator last, Result const& result, + std::forward_iterator_tag* + ) + { + return sprout::fixed::detail::copy_impl_fw(first, last, result, sprout::size(result)); + } + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::container_traits::static_size == sizeof...(Args) + 1, + typename sprout::fixed::result_of::algorithm::type + >::type + copy_impl_in( + sprout::next_iterator const& first, InputIterator, Result const& result, + typename sprout::container_traits::size_type, + Args const&... args + ) + { + return sprout::remake(result, sprout::size(result), args..., *first); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::container_traits::static_size != sizeof...(Args) + 1, + typename sprout::fixed::result_of::algorithm::type + >::type + copy_impl_in( + sprout::next_iterator const& first, InputIterator last, Result const& result, + typename sprout::container_traits::size_type size, + Args const&... args + ) + { + return first.base() != last && sizeof...(Args) + 1 < size + ? sprout::fixed::detail::copy_impl_in(sprout::next(first), last, result, size, args..., *first) + : sprout::detail::container_complate(result, args..., *first) + ; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::container_traits::static_size == 0, + typename sprout::fixed::result_of::algorithm::type + >::type + copy( + InputIterator, InputIterator, Result const& result, std::input_iterator_tag* ) { - return sprout::fixed::detail::copy_impl(first, last, result, sprout::size(result)); + return sprout::remake(result, sprout::size(result)); + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + sprout::container_traits::static_size != 0, + typename sprout::fixed::result_of::algorithm::type + >::type + copy( + InputIterator first, InputIterator last, Result const& result, + std::input_iterator_tag* + ) + { + return first != last + ? sprout::fixed::detail::copy_impl_in(sprout::make_next_iterator(first), last, result, sprout::size(result)) + : sprout::detail::container_complate(result) + ; } template diff --git a/sprout/iterator/adaptor.hpp b/sprout/iterator/adaptor.hpp index 9b5be44c..7a5ffa0a 100644 --- a/sprout/iterator/adaptor.hpp +++ b/sprout/iterator/adaptor.hpp @@ -33,5 +33,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_ITERATOR_ADAPTOR_HPP diff --git a/sprout/iterator/next_iterator.hpp b/sprout/iterator/next_iterator.hpp new file mode 100644 index 00000000..50780829 --- /dev/null +++ b/sprout/iterator/next_iterator.hpp @@ -0,0 +1,137 @@ +/*============================================================================= + Copyright (c) 2011-2013 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_ITERATOR_NEXT_ITERATOR_HPP +#define SPROUT_ITERATOR_NEXT_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // next_iterator + // + template + struct next_iterator + : public std::iterator< + std::forward_iterator_tag, + typename std::iterator_traits::value_type, + typename std::iterator_traits::difference_type, + typename std::iterator_traits::pointer, + typename std::iterator_traits::reference + > + { + public: + typedef Iterator iterator_type; + typedef std::forward_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::reference reference; + private: + typedef sprout::value_holder holder_type; + private: + holder_type holder_; + protected: + iterator_type current; + public: + next_iterator() = default; + SPROUT_CONSTEXPR next_iterator(next_iterator const& other) + : holder_(other.holder_), current(other.current) + {} + SPROUT_CONSTEXPR next_iterator(iterator_type it) + : holder_(*it), current(sprout::next(it)) + {} + template + SPROUT_CONSTEXPR next_iterator(next_iterator const& it) + : holder_(*it), current(it.base()) + {} + template + next_iterator& operator=(next_iterator const& it) { + next_iterator temp(it); + temp.swap(*this); + return *this; + } + SPROUT_CONSTEXPR iterator_type base() const { + return current; + } + SPROUT_CONSTEXPR reference operator*() const { + return *holder_; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &*(*this); + } + next_iterator& operator++() { + holder_ = holder_type(*current); + ++current; + return *this; + } + next_iterator operator++(int) { + next_iterator result(*this); + holder_ = holder_type(*current); + ++current; + return result; + } + SPROUT_CONSTEXPR next_iterator next() const { + return next_iterator(current); + } + void swap(next_iterator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(swap(holder_, other.holder_)) && SPROUT_NOEXCEPT_EXPR(swap(current, other.current)) + ) + { + swap(holder_, other.holder_); + swap(current, other.current); + } + }; + + template + inline SPROUT_CONSTEXPR bool + operator==(sprout::next_iterator const& lhs, sprout::next_iterator const& rhs) { + return lhs.base() == rhs.base(); + } + template + inline SPROUT_CONSTEXPR bool + operator!=(sprout::next_iterator const& lhs, sprout::next_iterator const& rhs) { + return !(lhs == rhs); + } + + // + // make_next_iterator + // + template + inline SPROUT_CONSTEXPR sprout::next_iterator + make_next_iterator(Iterator it) { + return sprout::next_iterator(it); + } + + // + // swap + // + template + inline void + swap(sprout::next_iterator& lhs, sprout::next_iterator& rhs) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + // + // iterator_next + // + template + inline SPROUT_CONSTEXPR sprout::next_iterator + iterator_next(sprout::next_iterator const& it) { + return it.next(); + } +} // namespace sprout + +#endif // #ifndef SPROUT_ITERATOR_NEXT_ITERATOR_HPP