diff --git a/sprout/iterator/distance.hpp b/sprout/iterator/distance.hpp index 2bdf8e89..5fc4efe0 100644 --- a/sprout/iterator/distance.hpp +++ b/sprout/iterator/distance.hpp @@ -22,6 +22,27 @@ namespace sprout_adl { namespace sprout { namespace iterator_detail { + template + inline SPROUT_CXX14_CONSTEXPR typename std::iterator_traits::difference_type + cxx14_distance(RandomAccessIterator first, RandomAccessIterator last, std::random_access_iterator_tag*) { + return last - first; + } + template + inline SPROUT_CXX14_CONSTEXPR typename std::iterator_traits::difference_type + cxx14_distance(InputIterator first, InputIterator last, std::input_iterator_tag*) { + typename std::iterator_traits::difference_type n = 0; + for (; first != last; ++first) { + ++n; + } + return n; + } + template + inline SPROUT_CXX14_CONSTEXPR typename std::iterator_traits::difference_type + cxx14_distance(InputIterator first, InputIterator last) { + typedef typename std::iterator_traits::iterator_category* category; + return sprout::iterator_detail::cxx14_distance(first, last, category()); + } + template inline SPROUT_CONSTEXPR typename std::enable_if< sprout::is_constant_distance_iterator::value, @@ -67,29 +88,29 @@ namespace sprout { ) ; } - template - inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type - iterator_distance(InputIterator first, InputIterator last, std::input_iterator_tag*) { - typedef sprout::pair::difference_type> type; - return sprout::iterator_detail::iterator_distance_impl(type(first, 0), last, 1).second; - } - template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_literal_type::value, typename std::iterator_traits::difference_type >::type - iterator_distance(InputIterator first, InputIterator last) { - typedef typename std::iterator_traits::iterator_category* category; - return sprout::iterator_detail::iterator_distance(first, last, category()); + iterator_distance(InputIterator first, InputIterator last, std::input_iterator_tag*) { + typedef sprout::pair::difference_type> type; + return sprout::iterator_detail::iterator_distance_impl(type(first, 0), last, 1).second; } template inline SPROUT_CONSTEXPR typename std::enable_if< !std::is_literal_type::value, typename std::iterator_traits::difference_type >::type + iterator_distance(InputIterator first, InputIterator last, std::input_iterator_tag*) { + return sprout::iterator_detail::cxx14_distance(first, last); + } + + template + inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type iterator_distance(InputIterator first, InputIterator last) { - return std::distance(first, last); + typedef typename std::iterator_traits::iterator_category* category; + return sprout::iterator_detail::iterator_distance(first, last, category()); } } // namespace iterator_detail } // namespace sprout @@ -110,9 +131,9 @@ namespace sprout { // // effect: // ADL callable iterator_distance(first, last) -> iterator_distance(first, last) - // otherwise, [first, last) is not LiteralType -> std::distance(first, last) - // otherwise, [first, last) is RandomAccessIterator && not Pointer -> last - first - // otherwise -> linearly count: first to last + // otherwise, [first, last) is RandomAccessIterator && ConstantDistanceIterator -> last - first + // otherwise, [first, last) is LiteralType -> linearly count: first to last + // otherwise -> cxx14_distance(first, last) // template inline SPROUT_CONSTEXPR typename std::iterator_traits::difference_type diff --git a/sprout/iterator/next.hpp b/sprout/iterator/next.hpp index b728791d..6f31f1cf 100644 --- a/sprout/iterator/next.hpp +++ b/sprout/iterator/next.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -24,36 +25,25 @@ namespace sprout_adl { namespace sprout { namespace iterator_detail { template - InputIterator - single_pass_next(InputIterator it, typename std::iterator_traits::difference_type n = 1) { - std::advance(it, n); + inline SPROUT_CXX14_CONSTEXPR InputIterator + cxx14_next(InputIterator it, typename std::iterator_traits::difference_type n = 1) { + sprout::advance(it, n); return it; } template - inline SPROUT_CONSTEXPR typename std::enable_if< - std::is_literal_type::value, - RandomAccessIterator - >::type + inline SPROUT_CONSTEXPR RandomAccessIterator next_impl(RandomAccessIterator const& it, std::random_access_iterator_tag*) { return it + 1; } - template - inline SPROUT_CONSTEXPR ForwardIterator - next_impl(ForwardIterator const& it, std::forward_iterator_tag*) { - return std::next(it); - } template inline SPROUT_CONSTEXPR InputIterator next_impl(InputIterator const& it, std::input_iterator_tag*) { - return sprout::iterator_detail::single_pass_next(it); + return sprout::iterator_detail::cxx14_next(it); } template - inline SPROUT_CONSTEXPR typename std::enable_if< - std::is_literal_type::value, - RandomAccessIterator - >::type + inline SPROUT_CONSTEXPR RandomAccessIterator next_impl( RandomAccessIterator const& it, typename std::iterator_traits::difference_type n, std::random_access_iterator_tag* @@ -121,18 +111,6 @@ namespace sprout { typedef typename std::iterator_traits::iterator_category* category; return sprout::iterator_detail::next_impl_1(it, n, category()); } - template - inline SPROUT_CONSTEXPR typename std::enable_if< - !std::is_literal_type::value, - ForwardIterator - >::type - next_impl( - ForwardIterator const& it, typename std::iterator_traits::difference_type n, - std::forward_iterator_tag* - ) - { - return std::next(it, n); - } template inline SPROUT_CONSTEXPR typename std::enable_if< !std::is_literal_type::value, @@ -143,7 +121,7 @@ namespace sprout { std::input_iterator_tag* ) { - return sprout::iterator_detail::single_pass_next(it, n); + return sprout::iterator_detail::cxx14_next(it, n); } template @@ -184,9 +162,8 @@ namespace sprout { // // effect: // ADL callable iterator_next(it) -> iterator_next(it) - // it is RandomAccessIterator && LiteralType -> it + 1 - // it is ForwardIterator -> std::next(it) - // otherwise -> single_pass_next(it) + // it is RandomAccessIterator -> it + 1 + // otherwise -> cxx14_next(it) // template inline SPROUT_CONSTEXPR InputIterator @@ -196,11 +173,10 @@ namespace sprout { // // effect: // ADL callable iterator_next(it, n) -> iterator_next(it, n) - // it is RandomAccessIterator && LiteralType -> it + n + // it is RandomAccessIterator -> it + n // it is LiteralType && n >= 0 -> sprout::next(it)... // it is LiteralType && n < 0 -> sprout::prev(it)... - // it is ForwardIterator -> std::next(it, n) - // otherwise -> single_pass_next(it, n) + // otherwise -> cxx14_next(it, n) // template inline SPROUT_CONSTEXPR InputIterator diff --git a/sprout/iterator/prev.hpp b/sprout/iterator/prev.hpp index 412b8786..d237d297 100644 --- a/sprout/iterator/prev.hpp +++ b/sprout/iterator/prev.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -21,25 +22,26 @@ namespace sprout_adl { namespace sprout { namespace iterator_detail { + template + inline SPROUT_CXX14_CONSTEXPR InputIterator + cxx14_prev(InputIterator it, typename std::iterator_traits::difference_type n = 1) { + sprout::advance(it, -n); + return it; + } + template - inline SPROUT_CONSTEXPR typename std::enable_if< - std::is_literal_type::value, - RandomAccessIterator - >::type + inline SPROUT_CONSTEXPR RandomAccessIterator prev_impl(RandomAccessIterator const& it, std::random_access_iterator_tag*) { return it - 1; } template inline SPROUT_CONSTEXPR BidirectionalIterator prev_impl(BidirectionalIterator const& it, std::bidirectional_iterator_tag*) { - return std::prev(it); + return sprout::iterator_detail::cxx14_prev(it); } template - inline SPROUT_CONSTEXPR typename std::enable_if< - std::is_literal_type::value, - RandomAccessIterator - >::type + inline SPROUT_CONSTEXPR RandomAccessIterator prev_impl( RandomAccessIterator const& it, typename std::iterator_traits::difference_type n, std::random_access_iterator_tag* @@ -94,7 +96,7 @@ namespace sprout { std::bidirectional_iterator_tag* ) { - return std::prev(it, n); + return sprout::iterator_detail::cxx14_prev(it, n); } template @@ -135,8 +137,8 @@ namespace sprout { // // effect: // ADL callable iterator_prev(it) -> iterator_prev(it) - // it is RandomAccessIterator && LiteralType -> it - 1 - // otherwise -> std::prev(it) + // it is RandomAccessIterator -> it - 1 + // otherwise -> cxx14_prev(it) // template inline SPROUT_CONSTEXPR BidirectionalIterator @@ -146,9 +148,10 @@ namespace sprout { // // effect: // ADL callable iterator_prev(it, n) -> iterator_prev(it, n) - // it is RandomAccessIterator && LiteralType -> it - n - // it is LiteralType -> sprout::prev(it)... || sprout::next(it)... - // otherwise -> std::prev(it, n) + // it is RandomAccessIterator -> it - n + // it is LiteralType && n >= 0 -> sprout::prev(it)... + // it is LiteralType && n < 0 -> sprout::next(it)... + // otherwise -> cxx14_prev(it, n) // template inline SPROUT_CONSTEXPR BidirectionalIterator diff --git a/sprout/iterator/type_traits/is_constant_distance_iterator.hpp b/sprout/iterator/type_traits/is_constant_distance_iterator.hpp index e5cb65e8..5ef6685d 100644 --- a/sprout/iterator/type_traits/is_constant_distance_iterator.hpp +++ b/sprout/iterator/type_traits/is_constant_distance_iterator.hpp @@ -13,7 +13,6 @@ #include namespace sprout { - // // is_constant_distance_iterator // @@ -21,7 +20,11 @@ namespace sprout { struct is_constant_distance_iterator : public std::integral_constant< bool, +#ifdef SPROUT_NO_CXX14_CONSTEXPR sprout::is_random_access_iterator::value && !std::is_pointer::value +#else // #ifdef SPROUT_NO_CXX14_CONSTEXPR + sprout::is_random_access_iterator::value +#endif // #ifdef SPROUT_NO_CXX14_CONSTEXPR > {}; } // namespace sprout