[sprout.iterator] support for C++14 constexpr iterator operation

This commit is contained in:
bolero-MURAKAMI 2013-10-08 18:45:10 +09:00
parent b192c5c214
commit 54b6a2be18
4 changed files with 69 additions and 66 deletions

View file

@ -22,6 +22,27 @@ namespace sprout_adl {
namespace sprout {
namespace iterator_detail {
template<typename RandomAccessIterator>
inline SPROUT_CXX14_CONSTEXPR typename std::iterator_traits<RandomAccessIterator>::difference_type
cxx14_distance(RandomAccessIterator first, RandomAccessIterator last, std::random_access_iterator_tag*) {
return last - first;
}
template<typename InputIterator>
inline SPROUT_CXX14_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
cxx14_distance(InputIterator first, InputIterator last, std::input_iterator_tag*) {
typename std::iterator_traits<InputIterator>::difference_type n = 0;
for (; first != last; ++first) {
++n;
}
return n;
}
template<typename InputIterator>
inline SPROUT_CXX14_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
cxx14_distance(InputIterator first, InputIterator last) {
typedef typename std::iterator_traits<InputIterator>::iterator_category* category;
return sprout::iterator_detail::cxx14_distance(first, last, category());
}
template<typename RandomAccessIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_constant_distance_iterator<RandomAccessIterator>::value,
@ -67,29 +88,29 @@ namespace sprout {
)
;
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
iterator_distance(InputIterator first, InputIterator last, std::input_iterator_tag*) {
typedef sprout::pair<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> type;
return sprout::iterator_detail::iterator_distance_impl(type(first, 0), last, 1).second;
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_literal_type<InputIterator>::value,
typename std::iterator_traits<InputIterator>::difference_type
>::type
iterator_distance(InputIterator first, InputIterator last) {
typedef typename std::iterator_traits<InputIterator>::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<InputIterator, typename std::iterator_traits<InputIterator>::difference_type> type;
return sprout::iterator_detail::iterator_distance_impl(type(first, 0), last, 1).second;
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
!std::is_literal_type<InputIterator>::value,
typename std::iterator_traits<InputIterator>::difference_type
>::type
iterator_distance(InputIterator first, InputIterator last, std::input_iterator_tag*) {
return sprout::iterator_detail::cxx14_distance(first, last);
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type
iterator_distance(InputIterator first, InputIterator last) {
return std::distance(first, last);
typedef typename std::iterator_traits<InputIterator>::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<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::iterator_traits<InputIterator>::difference_type

View file

@ -11,6 +11,7 @@
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/advance.hpp>
#include <sprout/iterator/next_fwd.hpp>
#include <sprout/iterator/prev_fwd.hpp>
#include <sprout/adl/not_found.hpp>
@ -24,36 +25,25 @@ namespace sprout_adl {
namespace sprout {
namespace iterator_detail {
template<typename InputIterator>
InputIterator
single_pass_next(InputIterator it, typename std::iterator_traits<InputIterator>::difference_type n = 1) {
std::advance(it, n);
inline SPROUT_CXX14_CONSTEXPR InputIterator
cxx14_next(InputIterator it, typename std::iterator_traits<InputIterator>::difference_type n = 1) {
sprout::advance(it, n);
return it;
}
template<typename RandomAccessIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_literal_type<RandomAccessIterator>::value,
RandomAccessIterator
>::type
inline SPROUT_CONSTEXPR RandomAccessIterator
next_impl(RandomAccessIterator const& it, std::random_access_iterator_tag*) {
return it + 1;
}
template<typename ForwardIterator>
inline SPROUT_CONSTEXPR ForwardIterator
next_impl(ForwardIterator const& it, std::forward_iterator_tag*) {
return std::next(it);
}
template<typename InputIterator>
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<typename RandomAccessIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_literal_type<RandomAccessIterator>::value,
RandomAccessIterator
>::type
inline SPROUT_CONSTEXPR RandomAccessIterator
next_impl(
RandomAccessIterator const& it, typename std::iterator_traits<RandomAccessIterator>::difference_type n,
std::random_access_iterator_tag*
@ -121,18 +111,6 @@ namespace sprout {
typedef typename std::iterator_traits<InputIterator>::iterator_category* category;
return sprout::iterator_detail::next_impl_1(it, n, category());
}
template<typename ForwardIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
!std::is_literal_type<ForwardIterator>::value,
ForwardIterator
>::type
next_impl(
ForwardIterator const& it, typename std::iterator_traits<ForwardIterator>::difference_type n,
std::forward_iterator_tag*
)
{
return std::next(it, n);
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
!std::is_literal_type<InputIterator>::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<typename InputIterator>
@ -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<typename InputIterator>
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<typename InputIterator>
inline SPROUT_CONSTEXPR InputIterator

View file

@ -11,6 +11,7 @@
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/advance.hpp>
#include <sprout/iterator/next_fwd.hpp>
#include <sprout/iterator/prev_fwd.hpp>
#include <sprout/adl/not_found.hpp>
@ -21,25 +22,26 @@ namespace sprout_adl {
namespace sprout {
namespace iterator_detail {
template<typename InputIterator>
inline SPROUT_CXX14_CONSTEXPR InputIterator
cxx14_prev(InputIterator it, typename std::iterator_traits<InputIterator>::difference_type n = 1) {
sprout::advance(it, -n);
return it;
}
template<typename RandomAccessIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_literal_type<RandomAccessIterator>::value,
RandomAccessIterator
>::type
inline SPROUT_CONSTEXPR RandomAccessIterator
prev_impl(RandomAccessIterator const& it, std::random_access_iterator_tag*) {
return it - 1;
}
template<typename BidirectionalIterator>
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<typename RandomAccessIterator>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_literal_type<RandomAccessIterator>::value,
RandomAccessIterator
>::type
inline SPROUT_CONSTEXPR RandomAccessIterator
prev_impl(
RandomAccessIterator const& it, typename std::iterator_traits<RandomAccessIterator>::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<typename BidirectionalIterator>
@ -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<typename BidirectionalIterator>
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<typename BidirectionalIterator>
inline SPROUT_CONSTEXPR BidirectionalIterator

View file

@ -13,7 +13,6 @@
#include <sprout/iterator/type_traits/is_iterator_of.hpp>
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<MaybeIterator>::value && !std::is_pointer<MaybeIterator>::value
#else // #ifdef SPROUT_NO_CXX14_CONSTEXPR
sprout::is_random_access_iterator<MaybeIterator>::value
#endif // #ifdef SPROUT_NO_CXX14_CONSTEXPR
>
{};
} // namespace sprout