forked from OSchip/llvm-project
[libc++] Assume that __wrap_iter always wraps a fancy pointer.
Not only do we conscientiously avoid using `__wrap_iter` for non-contiguous iterators (in vector, string, span...) but also we make the assumption (in regex) that `__wrap_iter<_Iter>` is contiguous for all `_Iter`. So `__wrap_iter<reverse_iterator<int*>>` should be considered IFNDR, and every `__wrap_iter` should correctly advertise contiguity in C++20. Drive-by simplify some type traits. Reviewed as part of https://reviews.llvm.org/D102781
This commit is contained in:
parent
13dd65b3a1
commit
fc9248877d
|
@ -428,7 +428,7 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*>
|
|||
|
||||
template <class _Tp, class _Up, bool = __has_iterator_category<iterator_traits<_Tp> >::value>
|
||||
struct __has_iterator_category_convertible_to
|
||||
: _BoolConstant<is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>::value>
|
||||
: is_convertible<typename iterator_traits<_Tp>::iterator_category, _Up>
|
||||
{};
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
|
@ -436,7 +436,7 @@ struct __has_iterator_category_convertible_to<_Tp, _Up, false> : false_type {};
|
|||
|
||||
template <class _Tp, class _Up, bool = __has_iterator_concept<_Tp>::value>
|
||||
struct __has_iterator_concept_convertible_to
|
||||
: _BoolConstant<is_convertible<typename _Tp::iterator_concept, _Up>::value>
|
||||
: is_convertible<typename _Tp::iterator_concept, _Up>
|
||||
{};
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
|
@ -454,10 +454,12 @@ struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_conver
|
|||
template <class _Tp>
|
||||
struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {};
|
||||
|
||||
// __is_cpp17_contiguous_iterator determines if an iterator is contiguous,
|
||||
// either because it advertises itself as such (in C++20) or because it
|
||||
// is a pointer type or a known trivial wrapper around a pointer type,
|
||||
// such as __wrap_iter<T*>.
|
||||
// __is_cpp17_contiguous_iterator determines if an iterator is known by
|
||||
// libc++ to be contiguous, either because it advertises itself as such
|
||||
// (in C++20) or because it is a pointer type or a known trivial wrapper
|
||||
// around a (possibly fancy) pointer type, such as __wrap_iter<T*>.
|
||||
// Such iterators receive special "contiguous" optimizations in
|
||||
// std::copy and std::sort.
|
||||
//
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
template <class _Tp>
|
||||
|
|
|
@ -1294,8 +1294,7 @@ public:
|
|||
typedef typename iterator_traits<iterator_type>::reference reference;
|
||||
typedef typename iterator_traits<iterator_type>::iterator_category iterator_category;
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
typedef _If<__is_cpp17_contiguous_iterator<_Iter>::value,
|
||||
contiguous_iterator_tag, iterator_category> iterator_concept;
|
||||
typedef contiguous_iterator_tag iterator_concept;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -1473,12 +1472,12 @@ private:
|
|||
|
||||
#if _LIBCPP_STD_VER <= 17
|
||||
template <class _It>
|
||||
struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : __is_cpp17_contiguous_iterator<_It> {};
|
||||
struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {};
|
||||
#endif
|
||||
|
||||
template <class _Iter>
|
||||
_LIBCPP_CONSTEXPR
|
||||
_EnableIf<__is_cpp17_contiguous_iterator<_Iter>::value, decltype(_VSTD::__to_address(declval<_Iter>()))>
|
||||
decltype(_VSTD::__to_address(declval<_Iter>()))
|
||||
__to_address(__wrap_iter<_Iter> __w) _NOEXCEPT {
|
||||
return _VSTD::__to_address(__w.base());
|
||||
}
|
||||
|
|
|
@ -138,6 +138,21 @@ public:
|
|||
};
|
||||
#endif
|
||||
|
||||
struct fake_deque_iterator : std::deque<int>::iterator {
|
||||
using element_type = int;
|
||||
};
|
||||
static_assert(std::__is_cpp17_random_access_iterator<fake_deque_iterator>::value, "");
|
||||
static_assert(!std::__is_cpp17_contiguous_iterator<fake_deque_iterator>::value, "");
|
||||
|
||||
#if TEST_STD_VER >= 20
|
||||
struct fake2_deque_iterator : std::deque<int>::iterator {
|
||||
using iterator_concept = std::contiguous_iterator_tag;
|
||||
using element_type = int;
|
||||
};
|
||||
static_assert(std::__is_cpp17_random_access_iterator<fake2_deque_iterator>::value, "");
|
||||
static_assert(std::__is_cpp17_contiguous_iterator<fake2_deque_iterator>::value, "");
|
||||
#endif
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// basic tests
|
||||
|
@ -178,21 +193,19 @@ int main(int, char**)
|
|||
|
||||
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<T *> >::value), "");
|
||||
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<T *> > >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<T *> > >::value), "");
|
||||
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_random_access_iterator> >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<my_random_access_iterator> > >::value), "");
|
||||
// Here my_random_access_iterator is standing in for some user's fancy pointer type, written pre-C++20.
|
||||
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_random_access_iterator> >::value), "");
|
||||
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");
|
||||
|
||||
#if TEST_STD_VER >= 20
|
||||
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<my_contiguous_iterator> >::value), "");
|
||||
static_assert(( std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_contiguous_iterator> > >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::reverse_iterator<my_contiguous_iterator> > >::value), "");
|
||||
#endif
|
||||
|
||||
// iterators in the libc++ test suite
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<output_iterator <char *> >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<cpp17_input_iterator <char *> >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<cpp17_input_iterator <char *> >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<forward_iterator <char *> >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<bidirectional_iterator<char *> >::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<random_access_iterator<char *> >::value), "");
|
||||
|
@ -228,14 +241,12 @@ int main(int, char**)
|
|||
static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::const_iterator> ::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::reverse_iterator> ::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::deque<int>::const_reverse_iterator> ::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::deque<int>::iterator> >::value), "");
|
||||
|
||||
// vector<bool> is random-access but not contiguous
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::iterator> ::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::const_iterator> ::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::reverse_iterator> ::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::vector<bool>::const_reverse_iterator> ::value), "");
|
||||
static_assert((!std::__is_cpp17_contiguous_iterator<std::__wrap_iter<std::vector<bool>::iterator> >::value), "");
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
static_assert(( std::__is_cpp17_contiguous_iterator<std::initializer_list<int>::iterator> ::value), "");
|
||||
|
|
Loading…
Reference in New Issue