brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.3 KiB · 3e465b3 Raw
371 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// std::ranges::end12// std::ranges::cend13 14#include <ranges>15 16#include <cassert>17#include <utility>18#include "test_macros.h"19#include "test_iterators.h"20 21using RangeEndT = decltype(std::ranges::end);22using RangeCEndT = decltype(std::ranges::cend);23 24static int globalBuff[8];25 26static_assert(!std::is_invocable_v<RangeEndT, int (&&)[]>);27static_assert(!std::is_invocable_v<RangeEndT, int (&)[]>);28static_assert(!std::is_invocable_v<RangeEndT, int (&&)[10]>);29static_assert( std::is_invocable_v<RangeEndT, int (&)[10]>);30static_assert(!std::is_invocable_v<RangeCEndT, int (&&)[]>);31static_assert(!std::is_invocable_v<RangeCEndT, int (&)[]>);32static_assert(!std::is_invocable_v<RangeCEndT, int (&&)[10]>);33static_assert( std::is_invocable_v<RangeCEndT, int (&)[10]>);34 35struct Incomplete;36static_assert(!std::is_invocable_v<RangeEndT, Incomplete(&&)[]>);37static_assert(!std::is_invocable_v<RangeEndT, Incomplete(&&)[42]>);38static_assert(!std::is_invocable_v<RangeCEndT, Incomplete(&&)[]>);39static_assert(!std::is_invocable_v<RangeCEndT, Incomplete(&&)[42]>);40 41struct EndMember {42  int x;43  const int *begin() const;44  constexpr const int *end() const { return &x; }45};46 47// Ensure that we can't call with rvalues with borrowing disabled.48static_assert( std::is_invocable_v<RangeEndT, EndMember &>);49static_assert(!std::is_invocable_v<RangeEndT, EndMember &&>);50static_assert( std::is_invocable_v<RangeEndT, EndMember const&>);51static_assert(!std::is_invocable_v<RangeEndT, EndMember const&&>);52static_assert( std::is_invocable_v<RangeCEndT, EndMember &>);53static_assert(!std::is_invocable_v<RangeCEndT, EndMember &&>);54static_assert( std::is_invocable_v<RangeCEndT, EndMember const&>);55static_assert(!std::is_invocable_v<RangeCEndT, EndMember const&&>);56 57constexpr bool testReturnTypes() {58  {59    int *x[2];60    ASSERT_SAME_TYPE(decltype(std::ranges::end(x)), int**);61    ASSERT_SAME_TYPE(decltype(std::ranges::cend(x)), int* const*);62  }63  {64    int x[2][2];65    ASSERT_SAME_TYPE(decltype(std::ranges::end(x)), int(*)[2]);66    ASSERT_SAME_TYPE(decltype(std::ranges::cend(x)), const int(*)[2]);67  }68  {69    struct Different {70      char *begin();71      sentinel_wrapper<char*>& end();72      short *begin() const;73      sentinel_wrapper<short*>& end() const;74    } x;75    ASSERT_SAME_TYPE(decltype(std::ranges::end(x)), sentinel_wrapper<char*>);76    ASSERT_SAME_TYPE(decltype(std::ranges::cend(x)), sentinel_wrapper<short*>);77  }78  return true;79}80 81constexpr bool testArray() {82  int a[2];83  assert(std::ranges::end(a) == a + 2);84  assert(std::ranges::cend(a) == a + 2);85 86  int b[2][2];87  assert(std::ranges::end(b) == b + 2);88  assert(std::ranges::cend(b) == b + 2);89 90  EndMember c[2];91  assert(std::ranges::end(c) == c + 2);92  assert(std::ranges::cend(c) == c + 2);93 94  return true;95}96 97struct EndMemberReturnsInt {98  int begin() const;99  int end() const;100};101static_assert(!std::is_invocable_v<RangeEndT, EndMemberReturnsInt const&>);102 103struct EndMemberReturnsVoidPtr {104  const void *begin() const;105  const void *end() const;106};107static_assert(!std::is_invocable_v<RangeEndT, EndMemberReturnsVoidPtr const&>);108 109struct PtrConvertible {110  operator int*() const;111};112struct PtrConvertibleEndMember {113  PtrConvertible begin() const;114  PtrConvertible end() const;115};116static_assert(!std::is_invocable_v<RangeEndT, PtrConvertibleEndMember const&>);117 118struct NoBeginMember {119  constexpr const int *end();120};121static_assert(!std::is_invocable_v<RangeEndT, NoBeginMember const&>);122 123struct NonConstEndMember {124  int x;125  constexpr int *begin() { return nullptr; }126  constexpr int *end() { return &x; }127};128static_assert( std::is_invocable_v<RangeEndT,  NonConstEndMember &>);129static_assert(!std::is_invocable_v<RangeEndT,  NonConstEndMember const&>);130static_assert(!std::is_invocable_v<RangeCEndT, NonConstEndMember &>);131static_assert(!std::is_invocable_v<RangeCEndT, NonConstEndMember const&>);132 133struct EnabledBorrowingEndMember {134  constexpr int *begin() const { return nullptr; }135  constexpr int *end() const { return &globalBuff[0]; }136};137 138template<>139inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingEndMember> = true;140 141struct EndMemberFunction {142  int x;143  constexpr const int *begin() const { return nullptr; }144  constexpr const int *end() const { return &x; }145  friend constexpr int *end(EndMemberFunction const&);146};147 148struct Empty { };149struct EmptyEndMember {150  Empty begin() const;151  Empty end() const;152};153static_assert(!std::is_invocable_v<RangeEndT, EmptyEndMember const&>);154 155struct EmptyPtrEndMember {156  Empty x;157  constexpr const Empty *begin() const { return nullptr; }158  constexpr const Empty *end() const { return &x; }159};160 161constexpr bool testEndMember() {162  EndMember a;163  assert(std::ranges::end(a) == &a.x);164  assert(std::ranges::cend(a) == &a.x);165 166  NonConstEndMember b;167  assert(std::ranges::end(b) == &b.x);168  static_assert(!std::is_invocable_v<RangeCEndT, decltype((b))>);169 170  EnabledBorrowingEndMember c;171  assert(std::ranges::end(std::move(c)) == &globalBuff[0]);172  assert(std::ranges::cend(std::move(c)) == &globalBuff[0]);173 174  EndMemberFunction d;175  assert(std::ranges::end(d) == &d.x);176  assert(std::ranges::cend(d) == &d.x);177 178  EmptyPtrEndMember e;179  assert(std::ranges::end(e) == &e.x);180  assert(std::ranges::cend(e) == &e.x);181 182  return true;183}184 185struct EndFunction {186  int x;187  friend constexpr const int *begin(EndFunction const&) { return nullptr; }188  friend constexpr const int *end(EndFunction const& bf) { return &bf.x; }189};190 191static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>);192static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);193 194static_assert( std::is_invocable_v<RangeEndT,  EndFunction const&>);195static_assert(!std::is_invocable_v<RangeEndT,  EndFunction &&>);196static_assert(std::is_invocable_v<RangeEndT, EndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic197static_assert( std::is_invocable_v<RangeCEndT, EndFunction const&>);198static_assert( std::is_invocable_v<RangeCEndT, EndFunction &>);199 200struct EndFunctionReturnsInt {201  friend constexpr int begin(EndFunctionReturnsInt const&);202  friend constexpr int end(EndFunctionReturnsInt const&);203};204static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsInt const&>);205 206struct EndFunctionReturnsVoidPtr {207  friend constexpr void *begin(EndFunctionReturnsVoidPtr const&);208  friend constexpr void *end(EndFunctionReturnsVoidPtr const&);209};210static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsVoidPtr const&>);211 212struct EndFunctionReturnsEmpty {213  friend constexpr Empty begin(EndFunctionReturnsEmpty const&);214  friend constexpr Empty end(EndFunctionReturnsEmpty const&);215};216static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsEmpty const&>);217 218struct EndFunctionReturnsPtrConvertible {219  friend constexpr PtrConvertible begin(EndFunctionReturnsPtrConvertible const&);220  friend constexpr PtrConvertible end(EndFunctionReturnsPtrConvertible const&);221};222static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsPtrConvertible const&>);223 224struct NoBeginFunction {225  friend constexpr const int *end(NoBeginFunction const&);226};227static_assert(!std::is_invocable_v<RangeEndT, NoBeginFunction const&>);228 229struct EndFunctionByValue {230  friend constexpr int *begin(EndFunctionByValue) { return nullptr; }231  friend constexpr int *end(EndFunctionByValue) { return &globalBuff[1]; }232};233static_assert(!std::is_invocable_v<RangeCEndT, EndFunctionByValue>);234 235struct EndFunctionEnabledBorrowing {236  friend constexpr int *begin(EndFunctionEnabledBorrowing) { return nullptr; }237  friend constexpr int *end(EndFunctionEnabledBorrowing) { return &globalBuff[2]; }238};239template<>240inline constexpr bool std::ranges::enable_borrowed_range<EndFunctionEnabledBorrowing> = true;241 242struct EndFunctionReturnsEmptyPtr {243  Empty x;244  friend constexpr const Empty *begin(EndFunctionReturnsEmptyPtr const&) { return nullptr; }245  friend constexpr const Empty *end(EndFunctionReturnsEmptyPtr const& bf) { return &bf.x; }246};247 248struct EndFunctionWithDataMember {249  int x;250  int end;251  friend constexpr const int *begin(EndFunctionWithDataMember const&) { return nullptr; }252  friend constexpr const int *end(EndFunctionWithDataMember const& bf) { return &bf.x; }253};254 255struct EndFunctionWithPrivateEndMember {256  int y;257  friend constexpr const int *begin(EndFunctionWithPrivateEndMember const&) { return nullptr; }258  friend constexpr const int *end(EndFunctionWithPrivateEndMember const& bf) { return &bf.y; }259private:260  const int *end() const;261};262 263struct BeginMemberEndFunction {264  int x;265  constexpr const int *begin() const { return nullptr; }266  friend constexpr const int *end(BeginMemberEndFunction const& bf) { return &bf.x; }267};268 269constexpr bool testEndFunction() {270  const EndFunction a{};271  assert(std::ranges::end(a) == &a.x);272  assert(std::ranges::cend(a) == &a.x);273  EndFunction aa{};274  assert(std::ranges::end(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic275  assert(std::ranges::cend(aa) == &aa.x);276 277  EndFunctionByValue b;278  assert(std::ranges::end(b) == &globalBuff[1]);279  assert(std::ranges::cend(b) == &globalBuff[1]);280 281  EndFunctionEnabledBorrowing c;282  assert(std::ranges::end(std::move(c)) == &globalBuff[2]);283  assert(std::ranges::cend(std::move(c)) == &globalBuff[2]);284 285  const EndFunctionReturnsEmptyPtr d{};286  assert(std::ranges::end(d) == &d.x);287  assert(std::ranges::cend(d) == &d.x);288  EndFunctionReturnsEmptyPtr dd{};289  assert(std::ranges::end(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic290  assert(std::ranges::cend(dd) == &dd.x);291 292  const EndFunctionWithDataMember e{};293  assert(std::ranges::end(e) == &e.x);294  assert(std::ranges::cend(e) == &e.x);295  EndFunctionWithDataMember ee{};296  assert(std::ranges::end(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic297  assert(std::ranges::cend(ee) == &ee.x);298 299  const EndFunctionWithPrivateEndMember f{};300  assert(std::ranges::end(f) == &f.y);301  assert(std::ranges::cend(f) == &f.y);302  EndFunctionWithPrivateEndMember ff{};303  assert(std::ranges::end(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic304  assert(std::ranges::cend(ff) == &ff.y);305 306  const BeginMemberEndFunction g{};307  assert(std::ranges::end(g) == &g.x);308  assert(std::ranges::cend(g) == &g.x);309  BeginMemberEndFunction gg{};310  assert(std::ranges::end(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic311  assert(std::ranges::cend(gg) == &gg.x);312 313  return true;314}315 316 317ASSERT_NOEXCEPT(std::ranges::end(std::declval<int (&)[10]>()));318ASSERT_NOEXCEPT(std::ranges::cend(std::declval<int (&)[10]>()));319 320struct NoThrowMemberEnd {321  ThrowingIterator<int> begin() const;322  ThrowingIterator<int> end() const noexcept; // auto(t.end()) doesn't throw323} ntme;324static_assert(noexcept(std::ranges::end(ntme)));325static_assert(noexcept(std::ranges::cend(ntme)));326 327struct NoThrowADLEnd {328  ThrowingIterator<int> begin() const;329  friend ThrowingIterator<int> end(NoThrowADLEnd&) noexcept;  // auto(end(t)) doesn't throw330  friend ThrowingIterator<int> end(const NoThrowADLEnd&) noexcept;331} ntae;332static_assert(noexcept(std::ranges::end(ntae)));333static_assert(noexcept(std::ranges::cend(ntae)));334 335struct NoThrowMemberEndReturnsRef {336  ThrowingIterator<int> begin() const;337  ThrowingIterator<int>& end() const noexcept; // auto(t.end()) may throw338} ntmerr;339static_assert(!noexcept(std::ranges::end(ntmerr)));340static_assert(!noexcept(std::ranges::cend(ntmerr)));341 342struct EndReturnsArrayRef {343    auto begin() const noexcept -> int(&)[10];344    auto end() const noexcept -> int(&)[10];345} erar;346static_assert(noexcept(std::ranges::end(erar)));347static_assert(noexcept(std::ranges::cend(erar)));348 349// Test ADL-proofing.350struct Incomplete;351template<class T> struct Holder { T t; };352static_assert(!std::is_invocable_v<RangeEndT, Holder<Incomplete>*>);353static_assert(!std::is_invocable_v<RangeEndT, Holder<Incomplete>*&>);354static_assert(!std::is_invocable_v<RangeCEndT, Holder<Incomplete>*>);355static_assert(!std::is_invocable_v<RangeCEndT, Holder<Incomplete>*&>);356 357int main(int, char**) {358  static_assert(testReturnTypes());359 360  testArray();361  static_assert(testArray());362 363  testEndMember();364  static_assert(testEndMember());365 366  testEndFunction();367  static_assert(testEndFunction());368 369  return 0;370}371