Closed
Description
std::prev(it, n)
could conceivably be well-formed for a non-bidirectional it
if n
is negative, however std::prev(it)
is always UB, and we can easily diagnose it at compile-time. Right now std::prev(non_bidi)
is a no-op, which is absolutely vexing.
https://godbolt.org/z/zaG3jTEqP
Potential patch:
diff --git a/libcxx/include/__iterator/prev.h b/libcxx/include/__iterator/prev.h
index e950d8dc4147..98883188312a 100644
--- a/libcxx/include/__iterator/prev.h
+++ b/libcxx/include/__iterator/prev.h
@@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIter, __enable_if_t<__has_input_iterator_category<_InputIter>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _InputIter
-prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) {
+prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n) {
// Calling `advance` with a negative value on a non-bidirectional iterator is a no-op in the current implementation.
// Note that this check duplicates the similar check in `std::advance`.
_LIBCPP_ASSERT_PEDANTIC(__n <= 0 || __has_bidirectional_iterator_category<_InputIter>::value,
@@ -35,6 +35,12 @@ prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n =
return __x;
}
+template <class _BidirectionalIterator,
+ __enable_if_t<__has_bidirectional_iterator_category<_BidirectionalIterator>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _BidirectionalIterator prev(_BidirectionalIterator __it) {
+ return std::prev(std::move(__it), 1);
+}
+
#if _LIBCPP_STD_VER >= 20
// [range.iter.op.prev]