mirror of
https://github.com/bolero-MURAKAMI/Sprout
synced 2024-11-12 21:09:01 +00:00
[sprout.iterator] support for C++14 constexpr iterator operation
This commit is contained in:
parent
b192c5c214
commit
54b6a2be18
4 changed files with 69 additions and 66 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue