brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.6 KiB · 3f7c174 Raw
355 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// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// template<class D>12//   requires is_class_v<D> && same_as<D, remove_cv_t<D>>13// class view_interface;14 15#include <ranges>16 17#include <cassert>18#include <utility>19#include "test_macros.h"20#include "test_iterators.h"21 22template<class T>23concept ValidViewInterfaceType = requires { typename std::ranges::view_interface<T>; };24 25struct Empty { };26 27static_assert(!ValidViewInterfaceType<void>);28static_assert(!ValidViewInterfaceType<void*>);29static_assert(!ValidViewInterfaceType<Empty*>);30static_assert(!ValidViewInterfaceType<Empty const>);31static_assert(!ValidViewInterfaceType<Empty &>);32static_assert( ValidViewInterfaceType<Empty>);33 34using InputIter = cpp20_input_iterator<const int*>;35 36struct InputRange : std::ranges::view_interface<InputRange> {37  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};38  constexpr InputIter begin() const { return InputIter(buff); }39  constexpr InputIter end() const { return InputIter(buff + 8); }40};41 42struct SizedInputRange : std::ranges::view_interface<SizedInputRange> {43  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};44  constexpr InputIter begin() const { return InputIter(buff); }45  constexpr sentinel_wrapper<InputIter> end() const { return sentinel_wrapper(InputIter(buff + 8)); }46  constexpr std::size_t size() const { return 8; }47};48static_assert(std::ranges::sized_range<SizedInputRange>);49 50struct NotSizedSentinel {51  using value_type = int;52  using difference_type = std::ptrdiff_t;53  using iterator_concept = std::forward_iterator_tag;54 55  explicit NotSizedSentinel() = default;56  explicit NotSizedSentinel(int*);57  int& operator*() const;58  NotSizedSentinel& operator++();59  NotSizedSentinel operator++(int);60  bool operator==(NotSizedSentinel const&) const;61};62static_assert(std::forward_iterator<NotSizedSentinel>);63 64using ForwardIter = forward_iterator<int*>;65 66// So that we conform to sized_sentinel_for.67constexpr std::ptrdiff_t operator-(const ForwardIter& x, const ForwardIter& y) {68    return base(x) - base(y);69}70 71struct ForwardRange : std::ranges::view_interface<ForwardRange> {72  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};73  constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }74  constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }75};76static_assert(std::ranges::view<ForwardRange>);77 78struct MoveOnlyForwardRange : std::ranges::view_interface<MoveOnlyForwardRange> {79  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};80  MoveOnlyForwardRange(MoveOnlyForwardRange const&) = delete;81  MoveOnlyForwardRange(MoveOnlyForwardRange &&) = default;82  MoveOnlyForwardRange& operator=(MoveOnlyForwardRange &&) = default;83  MoveOnlyForwardRange() = default;84  constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }85  constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }86};87static_assert(std::ranges::view<MoveOnlyForwardRange>);88 89struct MI : std::ranges::view_interface<InputRange>,90            std::ranges::view_interface<MoveOnlyForwardRange> {91};92static_assert(!std::ranges::view<MI>);93 94struct EmptyIsTrue : std::ranges::view_interface<EmptyIsTrue> {95  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};96  constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }97  constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }98  constexpr bool empty() const { return true; }99};100static_assert(std::ranges::view<EmptyIsTrue>);101 102struct SizeIsTen : std::ranges::view_interface<SizeIsTen> {103  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};104  constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }105  constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }106  constexpr std::size_t size() const { return 10; }107};108static_assert(std::ranges::view<SizeIsTen>);109 110using RAIter = random_access_iterator<int*>;111 112struct RARange : std::ranges::view_interface<RARange> {113  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};114  constexpr RAIter begin() const { return RAIter(const_cast<int*>(buff)); }115  constexpr RAIter end() const { return RAIter(const_cast<int*>(buff) + 8); }116};117static_assert(std::ranges::view<RARange>);118 119using ContIter = contiguous_iterator<const int*>;120 121struct ContRange : std::ranges::view_interface<ContRange> {122  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};123  constexpr ContIter begin() const { return ContIter(buff); }124  constexpr ContIter end() const { return ContIter(buff + 8); }125};126static_assert(std::ranges::view<ContRange>);127 128struct DataIsNull : std::ranges::view_interface<DataIsNull> {129  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};130  constexpr ContIter begin() const { return ContIter(buff); }131  constexpr ContIter end() const { return ContIter(buff + 8); }132  constexpr const int *data() const { return nullptr; }133};134static_assert(std::ranges::view<DataIsNull>);135 136struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison> {137  struct ResultType {138    bool value;139    constexpr operator bool() const { return value; }140  };141 142  struct SentinelType {143    int *base_;144    explicit SentinelType() = default;145    constexpr explicit SentinelType(int *base) : base_(base) {}146    friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) == sent.base_}; }147    friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) == sent.base_}; }148    friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) != sent.base_}; }149    friend constexpr ResultType operator!=(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) != sent.base_}; }150  };151 152  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};153  constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }154  constexpr SentinelType end() const { return SentinelType(const_cast<int*>(buff) + 8); }155};156static_assert(std::ranges::view<BoolConvertibleComparison>);157 158template<class T>159concept EmptyInvocable = requires (T const& obj) { obj.empty(); };160 161template<class T>162concept BoolOpInvocable = requires (T const& obj) { bool(obj); };163 164constexpr bool testEmpty() {165  static_assert(!EmptyInvocable<InputRange>);166  // LWG 3715: `view_interface::empty` is overconstrained167  static_assert(EmptyInvocable<SizedInputRange>);168  static_assert( EmptyInvocable<ForwardRange>);169 170  static_assert(!BoolOpInvocable<InputRange>);171  static_assert(BoolOpInvocable<SizedInputRange>);172  static_assert( BoolOpInvocable<ForwardRange>);173 174  SizedInputRange sizedInputRange;175  assert(!sizedInputRange.empty());176  assert(!static_cast<SizedInputRange const&>(sizedInputRange).empty());177 178  assert(sizedInputRange);179  assert(static_cast<SizedInputRange const&>(sizedInputRange));180 181  assert(!std::ranges::empty(sizedInputRange));182  assert(!std::ranges::empty(static_cast<SizedInputRange const&>(sizedInputRange)));183 184  ForwardRange forwardRange;185  assert(!forwardRange.empty());186  assert(!static_cast<ForwardRange const&>(forwardRange).empty());187 188  assert(forwardRange);189  assert(static_cast<ForwardRange const&>(forwardRange));190 191  assert(!std::ranges::empty(forwardRange));192  assert(!std::ranges::empty(static_cast<ForwardRange const&>(forwardRange)));193 194  EmptyIsTrue emptyTrue;195  assert(emptyTrue.empty());196  assert(static_cast<EmptyIsTrue const&>(emptyTrue).empty());197  assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::empty());198 199  assert(!emptyTrue);200  assert(!static_cast<EmptyIsTrue const&>(emptyTrue));201  assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::operator bool());202 203  assert(std::ranges::empty(emptyTrue));204  assert(std::ranges::empty(static_cast<EmptyIsTrue const&>(emptyTrue)));205 206  // Try calling empty on an rvalue.207  MoveOnlyForwardRange moveOnly;208  assert(!std::move(moveOnly).empty());209 210  BoolConvertibleComparison boolConv;211  ASSERT_NOT_NOEXCEPT(boolConv.empty());212 213  assert(!boolConv.empty());214  assert(!static_cast<const BoolConvertibleComparison&>(boolConv).empty());215 216  assert(boolConv);217  assert(static_cast<const BoolConvertibleComparison&>(boolConv));218 219  assert(!std::ranges::empty(boolConv));220  assert(!std::ranges::empty(static_cast<const BoolConvertibleComparison&>(boolConv)));221 222  return true;223}224 225template<class T>226concept DataInvocable = requires (T const& obj) { obj.data(); };227 228constexpr bool testData() {229  static_assert(!DataInvocable<ForwardRange>);230  static_assert( DataInvocable<ContRange>);231 232  ContRange contiguous;233  assert(contiguous.data() == contiguous.buff);234  assert(static_cast<ContRange const&>(contiguous).data() == contiguous.buff);235 236  assert(std::ranges::data(contiguous) == contiguous.buff);237  assert(std::ranges::data(static_cast<ContRange const&>(contiguous)) == contiguous.buff);238 239  DataIsNull dataNull;240  assert(dataNull.data() == nullptr);241  assert(static_cast<DataIsNull const&>(dataNull).data() == nullptr);242  assert(dataNull.std::ranges::view_interface<DataIsNull>::data() == dataNull.buff);243 244  assert(std::ranges::data(dataNull) == nullptr);245  assert(std::ranges::data(static_cast<DataIsNull const&>(dataNull)) == nullptr);246 247  return true;248}249 250template<class T>251concept SizeInvocable = requires (T const& obj) { obj.size(); };252 253constexpr bool testSize() {254  static_assert(!SizeInvocable<InputRange>);255  static_assert(!SizeInvocable<NotSizedSentinel>);256  static_assert( SizeInvocable<ForwardRange>);257 258  // Test the test.259  static_assert(std::same_as<decltype(std::declval<ForwardIter>() - std::declval<ForwardIter>()), std::ptrdiff_t>);260  using UnsignedSize = std::make_unsigned_t<std::ptrdiff_t>;261  using SignedSize = std::common_type_t<std::ptrdiff_t, std::make_signed_t<UnsignedSize>>;262  ForwardRange forwardRange;263  assert(forwardRange.size() == 8);264  assert(static_cast<ForwardRange const&>(forwardRange).size() == 8);265 266  assert(std::ranges::size(forwardRange) == 8);267  static_assert(std::same_as<decltype(std::ranges::size(std::declval<ForwardRange>())), UnsignedSize>);268  static_assert(std::same_as<decltype(std::ranges::ssize(std::declval<ForwardRange>())), SignedSize>);269 270  assert(std::ranges::size(static_cast<ForwardRange const&>(forwardRange)) == 8);271  static_assert(std::same_as<decltype(std::ranges::size(std::declval<ForwardRange const>())), UnsignedSize>);272  static_assert(std::same_as<decltype(std::ranges::ssize(std::declval<ForwardRange const>())), SignedSize>);273 274  SizeIsTen sizeTen;275  assert(sizeTen.size() == 10);276  assert(static_cast<SizeIsTen const&>(sizeTen).size() == 10);277  assert(sizeTen.std::ranges::view_interface<SizeIsTen>::size() == 8);278 279  assert(std::ranges::size(sizeTen) == 10);280  assert(std::ranges::size(static_cast<SizeIsTen const&>(sizeTen)) == 10);281 282  return true;283}284 285template<class T>286concept SubscriptInvocable = requires (T const& obj, std::size_t n) { obj[n]; };287 288constexpr bool testSubscript() {289  static_assert(!SubscriptInvocable<ForwardRange>);290  static_assert( SubscriptInvocable<RARange>);291 292  RARange randomAccess;293  assert(randomAccess[2] == 2);294  assert(static_cast<RARange const&>(randomAccess)[2] == 2);295  randomAccess[2] = 3;296  assert(randomAccess[2] == 3);297 298  return true;299}300 301template<class T>302concept FrontInvocable = requires (T const& obj) { obj.front(); };303 304template<class T>305concept BackInvocable = requires (T const& obj) { obj.back(); };306 307constexpr bool testFrontBack() {308  static_assert(!FrontInvocable<InputRange>);309  static_assert( FrontInvocable<ForwardRange>);310  static_assert(!BackInvocable<ForwardRange>);311  static_assert( BackInvocable<RARange>);312 313  ForwardRange forwardRange;314  assert(forwardRange.front() == 0);315  assert(static_cast<ForwardRange const&>(forwardRange).front() == 0);316  forwardRange.front() = 2;317  assert(forwardRange.front() == 2);318 319  RARange randomAccess;320  assert(randomAccess.front() == 0);321  assert(static_cast<RARange const&>(randomAccess).front() == 0);322  randomAccess.front() = 2;323  assert(randomAccess.front() == 2);324 325  assert(randomAccess.back() == 7);326  assert(static_cast<RARange const&>(randomAccess).back() == 7);327  randomAccess.back() = 2;328  assert(randomAccess.back() == 2);329 330  return true;331}332 333struct V1 : std::ranges::view_interface<V1> { };334struct V2 : std::ranges::view_interface<V2> { V1 base_; };335static_assert(sizeof(V2) == sizeof(V1));336 337int main(int, char**) {338  testEmpty();339  static_assert(testEmpty());340 341  testData();342  static_assert(testData());343 344  testSize();345  static_assert(testSize());346 347  testSubscript();348  static_assert(testSubscript());349 350  testFrontBack();351  static_assert(testFrontBack());352 353  return 0;354}355