266 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 30#if TEST_STD_VER >= 1731#include <string_view>32#endif33 34#if TEST_STD_VER >= 2035#include <span>36#endif37 38class T; // incomplete39 40class my_input_iterator41{42 struct tag : std::input_iterator_tag {};43 typedef my_input_iterator Self;44 int *state_;45public:46 typedef tag iterator_category;47 typedef int value_type;48 typedef int difference_type;49 typedef int* pointer;50 typedef int& reference;51 52 my_input_iterator();53 reference operator*() const;54 pointer operator->() const;55 56 Self& operator++();57 Self operator++(int);58 friend bool operator==(const Self&, const Self&);59 friend bool operator!=(const Self&, const Self&);60};61 62class my_random_access_iterator63{64 struct tag : std::random_access_iterator_tag {};65 typedef my_random_access_iterator Self;66 int *state_;67public:68 typedef tag iterator_category;69 typedef int value_type;70 typedef int difference_type;71 typedef int* pointer;72 typedef int& reference;73 74 my_random_access_iterator();75 reference operator*() const;76 pointer operator->() const;77 reference operator[](difference_type) const;78 79 Self& operator++();80 Self operator++(int);81 Self& operator--();82 Self operator--(int);83 friend Self& operator+=(Self&, difference_type);84 friend Self& operator-=(Self&, difference_type);85 friend Self operator+(Self, difference_type);86 friend Self operator+(difference_type, Self);87 friend Self operator-(Self, difference_type);88 friend difference_type operator-(Self, Self);89 friend bool operator==(const Self&, const Self&);90 friend bool operator!=(const Self&, const Self&);91 friend bool operator<(const Self&, const Self&);92 friend bool operator>(const Self&, const Self&);93 friend bool operator<=(const Self&, const Self&);94 friend bool operator>=(const Self&, const Self&);95};96 97#if TEST_STD_VER >= 2098class my_contiguous_iterator99{100 struct tag : std::contiguous_iterator_tag {};101 typedef my_contiguous_iterator Self;102 int *state_;103public:104 typedef tag iterator_category;105 typedef int value_type;106 typedef int difference_type;107 typedef int* pointer;108 typedef int& reference;109 typedef int element_type; // enable to_address via pointer_traits110 111 my_contiguous_iterator();112 reference operator*() const;113 pointer operator->() const;114 reference operator[](difference_type) const;115 116 Self& operator++();117 Self operator++(int);118 Self& operator--();119 Self operator--(int);120 friend Self& operator+=(Self&, difference_type);121 friend Self& operator-=(Self&, difference_type);122 friend Self operator+(Self, difference_type);123 friend Self operator+(difference_type, Self);124 friend Self operator-(Self, difference_type);125 friend difference_type operator-(Self, Self);126 friend bool operator==(const Self&, const Self&);127 friend bool operator!=(const Self&, const Self&);128 friend bool operator<(const Self&, const Self&);129 friend bool operator>(const Self&, const Self&);130 friend bool operator<=(const Self&, const Self&);131 friend bool operator>=(const Self&, const Self&);132};133#endif134 135struct fake_deque_iterator : std::deque<int>::iterator {136 using element_type = int;137};138static_assert(std::__has_random_access_iterator_category<fake_deque_iterator>::value, "");139static_assert(!std::__libcpp_is_contiguous_iterator<fake_deque_iterator>::value, "");140 141#if TEST_STD_VER >= 20142struct fake2_deque_iterator : std::deque<int>::iterator {143 using iterator_concept = std::contiguous_iterator_tag;144 using element_type = int;145};146static_assert(std::__has_random_access_iterator_category<fake2_deque_iterator>::value, "");147static_assert(std::__libcpp_is_contiguous_iterator<fake2_deque_iterator>::value, "");148#endif149 150int main(int, char**)151{152// basic tests153 static_assert(( std::__libcpp_is_contiguous_iterator<char *>::value), "");154 static_assert(( std::__libcpp_is_contiguous_iterator<const char *>::value), "");155 static_assert(( std::__libcpp_is_contiguous_iterator<int *>::value), "");156 static_assert(( std::__libcpp_is_contiguous_iterator<int **>::value), "");157 static_assert(( std::__libcpp_is_contiguous_iterator<T *>::value), "");158 159 static_assert((!std::__libcpp_is_contiguous_iterator<my_input_iterator>::value), "");160 static_assert((!std::__libcpp_is_contiguous_iterator<my_random_access_iterator>::value), "");161#if TEST_STD_VER >= 20162 static_assert(( std::__libcpp_is_contiguous_iterator<my_contiguous_iterator>::value), "");163#endif164 165 // move_iterator changes value category, which makes it pretty sketchy to use in optimized codepaths166 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<char *> >::value), "");167 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<const char *> >::value), "");168 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<int *> >::value), "");169 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<T *> >::value), "");170 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<my_random_access_iterator> >::value), "");171#if TEST_STD_VER >= 20172 static_assert((!std::__libcpp_is_contiguous_iterator<std::move_iterator<my_contiguous_iterator> >::value), "");173#endif174 175 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<char *> >::value), "");176 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<const char *> >::value), "");177 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<int *> >::value), "");178 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<T *> >::value), "");179 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<my_random_access_iterator> >::value), "");180#if TEST_STD_VER >= 20181 static_assert((!std::__libcpp_is_contiguous_iterator<std::reverse_iterator<my_contiguous_iterator> >::value), "");182#endif183 184 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<char *> >::value), "");185 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<const char *> >::value), "");186 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<int *> >::value), "");187 188 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<T *> >::value), "");189 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<T *> > >::value), "");190 191 // Here my_random_access_iterator is standing in for some user's fancy pointer type, written pre-C++20.192 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<my_random_access_iterator> >::value), "");193 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_random_access_iterator> > >::value), "");194 195#if TEST_STD_VER >= 20196 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<my_contiguous_iterator> >::value), "");197 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<std::__wrap_iter<my_contiguous_iterator> > >::value), "");198#endif199 200// iterators in the libc++ test suite201 static_assert((!std::__libcpp_is_contiguous_iterator<cpp17_output_iterator <char *> >::value), "");202 static_assert((!std::__libcpp_is_contiguous_iterator<cpp17_input_iterator <char *> >::value), "");203 static_assert((!std::__libcpp_is_contiguous_iterator<forward_iterator <char *> >::value), "");204 static_assert((!std::__libcpp_is_contiguous_iterator<bidirectional_iterator<char *> >::value), "");205 static_assert((!std::__libcpp_is_contiguous_iterator<random_access_iterator<char *> >::value), "");206#if TEST_STD_VER >= 20207 static_assert(( std::__libcpp_is_contiguous_iterator<contiguous_iterator <char *> >::value), "");208#endif209 static_assert((!std::__libcpp_is_contiguous_iterator<ThrowingIterator <char *> >::value), "");210 static_assert((!std::__libcpp_is_contiguous_iterator<NonThrowingIterator <char *> >::value), "");211 212//213// iterators from libc++'s containers214//215 216// vector217 static_assert(( std::__libcpp_is_contiguous_iterator<std::vector<int>::iterator> ::value), "");218 static_assert(( std::__libcpp_is_contiguous_iterator<std::vector<int>::const_iterator> ::value), "");219 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<int>::reverse_iterator> ::value), "");220 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<int>::const_reverse_iterator> ::value), "");221 static_assert(( std::__libcpp_is_contiguous_iterator<std::__wrap_iter<std::vector<int>::iterator> >::value), "");222 223// string224 static_assert(( std::__libcpp_is_contiguous_iterator<std::string::iterator> ::value), "");225 static_assert(( std::__libcpp_is_contiguous_iterator<std::string::const_iterator> ::value), "");226 static_assert((!std::__libcpp_is_contiguous_iterator<std::string::reverse_iterator> ::value), "");227 static_assert((!std::__libcpp_is_contiguous_iterator<std::string::const_reverse_iterator>::value), "");228#ifndef TEST_HAS_NO_WIDE_CHARACTERS229 static_assert(( std::__libcpp_is_contiguous_iterator<std::wstring::iterator> ::value), "");230 static_assert(( std::__libcpp_is_contiguous_iterator<std::wstring::const_iterator> ::value), "");231 static_assert((!std::__libcpp_is_contiguous_iterator<std::wstring::reverse_iterator> ::value), "");232 static_assert((!std::__libcpp_is_contiguous_iterator<std::wstring::const_reverse_iterator>::value), "");233#endif234 235// deque is random-access but not contiguous236 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::iterator> ::value), "");237 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::const_iterator> ::value), "");238 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::reverse_iterator> ::value), "");239 static_assert((!std::__libcpp_is_contiguous_iterator<std::deque<int>::const_reverse_iterator> ::value), "");240 241// vector<bool> is random-access but not contiguous242 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::iterator> ::value), "");243 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::const_iterator> ::value), "");244 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::reverse_iterator> ::value), "");245 static_assert((!std::__libcpp_is_contiguous_iterator<std::vector<bool>::const_reverse_iterator> ::value), "");246 247#if TEST_STD_VER >= 11248 static_assert(( std::__libcpp_is_contiguous_iterator<std::initializer_list<int>::iterator> ::value), "");249 static_assert(( std::__libcpp_is_contiguous_iterator<std::initializer_list<int>::const_iterator>::value), "");250#endif251 252#if TEST_STD_VER >= 17253 static_assert(( std::__libcpp_is_contiguous_iterator<std::string_view::iterator> ::value), "");254 static_assert(( std::__libcpp_is_contiguous_iterator<std::string_view::const_iterator>::value), "");255#endif256 257#if TEST_STD_VER >= 20258 static_assert(( std::__libcpp_is_contiguous_iterator<std::span< int>::iterator> ::value), "");259 static_assert((!std::__libcpp_is_contiguous_iterator<std::span< int>::reverse_iterator>::value), "");260 static_assert(( std::__libcpp_is_contiguous_iterator<std::span<const int>::iterator> ::value), "");261 static_assert((!std::__libcpp_is_contiguous_iterator<std::span<const int>::reverse_iterator>::value), "");262#endif263 264 return 0;265}266