177 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9 10// <iterator>11 12// __libcpp_is_contiguous_iterator<_Tp>13 14// __libcpp_is_contiguous_iterator determines if an iterator is contiguous,15// either because it advertises itself as such (in C++20) or because it16// is a pointer type or a known trivial wrapper around a pointer type,17// such as __wrap_iter<T*>.18//19 20#include <cassert>21#include <deque>22#include <initializer_list>23#include <iterator>24#include <string>25#include <vector>26 27#include "test_macros.h"28#include "test_iterators.h"29 30class T; // incomplete31 32class my_input_iterator33{34 struct tag : std::input_iterator_tag {};35 typedef my_input_iterator Self;36 int *state_;37public:38 typedef tag iterator_category;39 typedef int value_type;40 typedef int difference_type;41 typedef int* pointer;42 typedef int& reference;43 44 my_input_iterator();45 reference operator*() const;46 pointer operator->() const;47 48 Self& operator++();49 Self operator++(int);50 friend bool operator==(const Self&, const Self&);51 friend bool operator!=(const Self&, const Self&);52};53 54class my_random_access_iterator55{56 struct tag : std::random_access_iterator_tag {};57 typedef my_random_access_iterator Self;58 int *state_;59public:60 typedef tag iterator_category;61 typedef int value_type;62 typedef int difference_type;63 typedef int* pointer;64 typedef int& reference;65 66 my_random_access_iterator();67 reference operator*() const;68 pointer operator->() const;69 reference operator[](difference_type) const;70 71 Self& operator++();72 Self operator++(int);73 Self& operator--();74 Self operator--(int);75 friend Self& operator+=(Self&, difference_type);76 friend Self& operator-=(Self&, difference_type);77 friend Self operator+(Self, difference_type);78 friend Self operator+(difference_type, Self);79 friend Self operator-(Self, difference_type);80 friend difference_type operator-(Self, Self);81 friend bool operator==(const Self&, const Self&);82 friend bool operator!=(const Self&, const Self&);83 friend bool operator<(const Self&, const Self&);84 friend bool operator>(const Self&, const Self&);85 friend bool operator<=(const Self&, const Self&);86 friend bool operator>=(const Self&, const Self&);87};88 89struct fake_deque_iterator : std::deque<int>::iterator {90 using element_type = int;91};92static_assert(std::__has_random_access_iterator_category<fake_deque_iterator>::value, "");93static_assert(!std::__libcpp_is_contiguous_iterator<fake_deque_iterator>::value, "");94 95int main(int, char**)96{97// basic tests98 static_assert(( std::__libcpp_is_contiguous_iterator<char *>::value), "");99 static_assert(( std::__libcpp_is_contiguous_iterator<const char *>::value), "");100 static_assert(( std::__libcpp_is_contiguous_iterator<int *>::value), "");101 static_assert(( std::__libcpp_is_contiguous_iterator<int **>::value), "");102 static_assert(( std::__libcpp_is_contiguous_iterator<T *>::value), "");103 104 static_assert((!std::__libcpp_is_contiguous_iterator<my_input_iterator>::value), "");105 static_assert((!std::__libcpp_is_contiguous_iterator<my_random_access_iterator>::value), "");106 107 // move_iterator changes value category, which makes it pretty sketchy to use in optimized codepaths108 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<char *> >::value), "");109 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<const char *> >::value), "");110 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<int *> >::value), "");111 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<T *> >::value), "");112 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<my_random_access_iterator> >::value), "");113 114 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<char *> >::value), "");115 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<const char *> >::value), "");116 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<int *> >::value), "");117 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<T *> >::value), "");118 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<my_random_access_iterator> >::value), "");119 120 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<char *> >::value), "");121 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<const char *> >::value), "");122 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<int *> >::value), "");123 124 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<T *> >::value), "");125 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<T *> > >::value), "");126 127 // Here my_random_access_iterator is standing in for some user's fancy pointer type, written pre-C++20.128 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<my_random_access_iterator> >::value), "");129 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");130 131// iterators in the libc++ test suite132 static_assert((!std::__libcpp_is_contiguous_iterator<cpp17_output_iterator <char *> >::value), "");133 static_assert((!std::__libcpp_is_contiguous_iterator<cpp17_input_iterator <char *> >::value), "");134 static_assert((!std::__libcpp_is_contiguous_iterator<forward_iterator <char *> >::value), "");135 static_assert((!std::__libcpp_is_contiguous_iterator<bidirectional_iterator<char *> >::value), "");136 static_assert((!std::__libcpp_is_contiguous_iterator<random_access_iterator<char *> >::value), "");137 static_assert((!std::__libcpp_is_contiguous_iterator<ThrowingIterator <char *> >::value), "");138 static_assert((!std::__libcpp_is_contiguous_iterator<NonThrowingIterator <char *> >::value), "");139 140//141// iterators from libc++'s containers142//143 144// vector145 static_assert(( std::__libcpp_is_contiguous_iterator<std::vector<int>::iterator> ::value), "");146 static_assert(( std::__libcpp_is_contiguous_iterator<std::vector<int>::const_iterator> ::value), "");147 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<int>::reverse_iterator> ::value), "");148 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<int>::const_reverse_iterator> ::value), "");149 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<std::vector<int>::iterator> >::value), "");150 151// string152 static_assert(( std::__libcpp_is_contiguous_iterator<std::string::iterator> ::value), "");153 static_assert(( std::__libcpp_is_contiguous_iterator<std::string::const_iterator> ::value), "");154 static_assert((!std::__libcpp_is_contiguous_iterator<std::string::reverse_iterator> ::value), "");155 static_assert((!std::__libcpp_is_contiguous_iterator<std::string::const_reverse_iterator>::value), "");156#ifndef TEST_HAS_NO_WIDE_CHARACTERS157 static_assert(( std::__libcpp_is_contiguous_iterator<std::wstring::iterator> ::value), "");158 static_assert(( std::__libcpp_is_contiguous_iterator<std::wstring::const_iterator> ::value), "");159 static_assert((!std::__libcpp_is_contiguous_iterator<std::wstring::reverse_iterator> ::value), "");160 static_assert((!std::__libcpp_is_contiguous_iterator<std::wstring::const_reverse_iterator>::value), "");161#endif162 163// deque is random-access but not contiguous164 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::iterator> ::value), "");165 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::const_iterator> ::value), "");166 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::reverse_iterator> ::value), "");167 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::const_reverse_iterator> ::value), "");168 169// vector<bool> is random-access but not contiguous170 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::iterator> ::value), "");171 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::const_iterator> ::value), "");172 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::reverse_iterator> ::value), "");173 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::const_reverse_iterator> ::value), "");174 175 return 0;176}177