brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.8 KiB · 3997f38 Raw
522 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::rbegin12// std::ranges::crbegin13 14#include <ranges>15 16#include <cassert>17#include <utility>18#include "test_macros.h"19#include "test_iterators.h"20 21using RangeRBeginT = decltype(std::ranges::rbegin);22using RangeCRBeginT = decltype(std::ranges::crbegin);23 24static int globalBuff[8];25 26static_assert(!std::is_invocable_v<RangeRBeginT, int (&&)[10]>);27static_assert( std::is_invocable_v<RangeRBeginT, int (&)[10]>);28static_assert(!std::is_invocable_v<RangeRBeginT, int (&&)[]>);29static_assert(!std::is_invocable_v<RangeRBeginT, int (&)[]>);30static_assert(!std::is_invocable_v<RangeCRBeginT, int (&&)[10]>);31static_assert( std::is_invocable_v<RangeCRBeginT, int (&)[10]>);32static_assert(!std::is_invocable_v<RangeCRBeginT, int (&&)[]>);33static_assert(!std::is_invocable_v<RangeCRBeginT, int (&)[]>);34 35struct Incomplete;36 37static_assert(!std::is_invocable_v<RangeRBeginT, Incomplete(&&)[]>);38static_assert(!std::is_invocable_v<RangeRBeginT, const Incomplete(&&)[]>);39static_assert(!std::is_invocable_v<RangeCRBeginT, Incomplete(&&)[]>);40static_assert(!std::is_invocable_v<RangeCRBeginT, const Incomplete(&&)[]>);41 42static_assert(!std::is_invocable_v<RangeRBeginT, Incomplete(&&)[10]>);43static_assert(!std::is_invocable_v<RangeRBeginT, const Incomplete(&&)[10]>);44static_assert(!std::is_invocable_v<RangeCRBeginT, Incomplete(&&)[10]>);45static_assert(!std::is_invocable_v<RangeCRBeginT, const Incomplete(&&)[10]>);46 47// This case is IFNDR; we handle it SFINAE-friendly.48LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeRBeginT, Incomplete(&)[]>);49LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeRBeginT, const Incomplete(&)[]>);50LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, Incomplete(&)[]>);51LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, const Incomplete(&)[]>);52 53// This case is IFNDR; we handle it SFINAE-friendly.54LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeRBeginT, Incomplete(&)[10]>);55LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeRBeginT, const Incomplete(&)[10]>);56LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, Incomplete(&)[10]>);57LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCRBeginT, const Incomplete(&)[10]>);58 59struct RBeginMember {60  int x;61  constexpr const int *rbegin() const { return &x; }62};63 64// Ensure that we can't call with rvalues with borrowing disabled.65static_assert( std::is_invocable_v<RangeRBeginT, RBeginMember &>);66static_assert(!std::is_invocable_v<RangeRBeginT, RBeginMember &&>);67static_assert( std::is_invocable_v<RangeRBeginT, RBeginMember const&>);68static_assert(!std::is_invocable_v<RangeRBeginT, RBeginMember const&&>);69static_assert( std::is_invocable_v<RangeCRBeginT, RBeginMember &>);70static_assert(!std::is_invocable_v<RangeCRBeginT, RBeginMember &&>);71static_assert( std::is_invocable_v<RangeCRBeginT, RBeginMember const&>);72static_assert(!std::is_invocable_v<RangeCRBeginT, RBeginMember const&&>);73 74constexpr bool testReturnTypes() {75  {76    int *x[2];77    ASSERT_SAME_TYPE(decltype(std::ranges::rbegin(x)), std::reverse_iterator<int**>);78    ASSERT_SAME_TYPE(decltype(std::ranges::crbegin(x)), std::reverse_iterator<int* const*>);79  }80  {81    int x[2][2];82    ASSERT_SAME_TYPE(decltype(std::ranges::rbegin(x)), std::reverse_iterator<int(*)[2]>);83    ASSERT_SAME_TYPE(decltype(std::ranges::crbegin(x)), std::reverse_iterator<const int(*)[2]>);84  }85  {86    struct Different {87      char*& rbegin();88      short*& rbegin() const;89    } x;90    ASSERT_SAME_TYPE(decltype(std::ranges::rbegin(x)), char*);91    ASSERT_SAME_TYPE(decltype(std::ranges::crbegin(x)), short*);92  }93  return true;94}95 96constexpr bool testArray() {97  int a[2];98  assert(std::ranges::rbegin(a).base() == a + 2);99  assert(std::ranges::crbegin(a).base() == a + 2);100 101  int b[2][2];102  assert(std::ranges::rbegin(b).base() == b + 2);103  assert(std::ranges::crbegin(b).base() == b + 2);104 105  RBeginMember c[2];106  assert(std::ranges::rbegin(c).base() == c + 2);107  assert(std::ranges::crbegin(c).base() == c + 2);108 109  return true;110}111 112struct RBeginMemberReturnsInt {113  int rbegin() const;114};115static_assert(!std::is_invocable_v<RangeRBeginT, RBeginMemberReturnsInt const&>);116 117struct RBeginMemberReturnsVoidPtr {118  const void *rbegin() const;119};120static_assert(!std::is_invocable_v<RangeRBeginT, RBeginMemberReturnsVoidPtr const&>);121 122struct PtrConvertibleRBeginMember {123  struct iterator { operator int*() const; };124  iterator rbegin() const;125};126static_assert(!std::is_invocable_v<RangeRBeginT, PtrConvertibleRBeginMember const&>);127 128struct NonConstRBeginMember {129  int x;130  constexpr int* rbegin() { return &x; }131};132static_assert( std::is_invocable_v<RangeRBeginT,  NonConstRBeginMember &>);133static_assert(!std::is_invocable_v<RangeRBeginT,  NonConstRBeginMember const&>);134static_assert(!std::is_invocable_v<RangeCRBeginT, NonConstRBeginMember &>);135static_assert(!std::is_invocable_v<RangeCRBeginT, NonConstRBeginMember const&>);136 137struct EnabledBorrowingRBeginMember {138  constexpr int *rbegin() const { return globalBuff; }139};140template<>141inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingRBeginMember> = true;142 143struct RBeginMemberFunction {144  int x;145  constexpr const int *rbegin() const { return &x; }146  friend int* rbegin(RBeginMemberFunction const&);147};148 149struct EmptyPtrRBeginMember {150  struct Empty {};151  Empty x;152  constexpr const Empty* rbegin() const { return &x; }153};154 155constexpr bool testRBeginMember() {156  RBeginMember a;157  assert(std::ranges::rbegin(a) == &a.x);158  assert(std::ranges::crbegin(a) == &a.x);159  static_assert(!std::is_invocable_v<RangeRBeginT, RBeginMember&&>);160  static_assert(!std::is_invocable_v<RangeCRBeginT, RBeginMember&&>);161 162  NonConstRBeginMember b;163  assert(std::ranges::rbegin(b) == &b.x);164  static_assert(!std::is_invocable_v<RangeCRBeginT, NonConstRBeginMember&>);165 166  EnabledBorrowingRBeginMember c;167  assert(std::ranges::rbegin(c) == globalBuff);168  assert(std::ranges::crbegin(c) == globalBuff);169  assert(std::ranges::rbegin(std::move(c)) == globalBuff);170  assert(std::ranges::crbegin(std::move(c)) == globalBuff);171 172  RBeginMemberFunction d;173  assert(std::ranges::rbegin(d) == &d.x);174  assert(std::ranges::crbegin(d) == &d.x);175 176  EmptyPtrRBeginMember e;177  assert(std::ranges::rbegin(e) == &e.x);178  assert(std::ranges::crbegin(e) == &e.x);179 180  return true;181}182 183 184struct RBeginFunction {185  int x;186  friend constexpr const int* rbegin(RBeginFunction const& bf) { return &bf.x; }187};188static_assert( std::is_invocable_v<RangeRBeginT,  RBeginFunction const&>);189static_assert(!std::is_invocable_v<RangeRBeginT,  RBeginFunction &&>);190static_assert(191    std::is_invocable_v<RangeRBeginT, RBeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic192static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction const&>);193static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction &>);194 195struct RBeginFunctionReturnsInt {196  friend int rbegin(RBeginFunctionReturnsInt const&);197};198static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunctionReturnsInt const&>);199 200struct RBeginFunctionReturnsVoidPtr {201  friend void *rbegin(RBeginFunctionReturnsVoidPtr const&);202};203static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunctionReturnsVoidPtr const&>);204 205struct RBeginFunctionReturnsEmpty {206  struct Empty {};207  friend Empty rbegin(RBeginFunctionReturnsEmpty const&);208};209static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunctionReturnsEmpty const&>);210 211struct RBeginFunctionReturnsPtrConvertible {212  struct iterator { operator int*() const; };213  friend iterator rbegin(RBeginFunctionReturnsPtrConvertible const&);214};215static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunctionReturnsPtrConvertible const&>);216 217struct RBeginFunctionByValue {218  friend constexpr int *rbegin(RBeginFunctionByValue) { return globalBuff + 1; }219};220static_assert(!std::is_invocable_v<RangeCRBeginT, RBeginFunctionByValue>);221 222struct RBeginFunctionEnabledBorrowing {223  friend constexpr int *rbegin(RBeginFunctionEnabledBorrowing) { return globalBuff + 2; }224};225template<>226inline constexpr bool std::ranges::enable_borrowed_range<RBeginFunctionEnabledBorrowing> = true;227 228struct RBeginFunctionReturnsEmptyPtr {229  struct Empty {};230  Empty x;231  friend constexpr const Empty *rbegin(RBeginFunctionReturnsEmptyPtr const& bf) { return &bf.x; }232};233 234struct RBeginFunctionWithDataMember {235  int x;236  int rbegin;237  friend constexpr const int *rbegin(RBeginFunctionWithDataMember const& bf) { return &bf.x; }238};239 240struct RBeginFunctionWithPrivateBeginMember {241  int y;242  friend constexpr const int *rbegin(RBeginFunctionWithPrivateBeginMember const& bf) { return &bf.y; }243private:244  const int *rbegin() const;245};246 247constexpr bool testRBeginFunction() {248  RBeginFunction a{};249  const RBeginFunction aa{};250  assert(std::ranges::rbegin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic251  assert(std::ranges::crbegin(a) == &a.x);252  assert(std::ranges::rbegin(aa) == &aa.x);253  assert(std::ranges::crbegin(aa) == &aa.x);254 255  RBeginFunctionByValue b{};256  const RBeginFunctionByValue bb{};257  assert(std::ranges::rbegin(b) == globalBuff + 1);258  assert(std::ranges::crbegin(b) == globalBuff + 1);259  assert(std::ranges::rbegin(bb) == globalBuff + 1);260  assert(std::ranges::crbegin(bb) == globalBuff + 1);261 262  RBeginFunctionEnabledBorrowing c{};263  const RBeginFunctionEnabledBorrowing cc{};264  assert(std::ranges::rbegin(std::move(c)) == globalBuff + 2);265  assert(std::ranges::crbegin(std::move(c)) == globalBuff + 2);266  assert(std::ranges::rbegin(std::move(cc)) == globalBuff + 2);267  assert(std::ranges::crbegin(std::move(cc)) == globalBuff + 2);268 269  RBeginFunctionReturnsEmptyPtr d{};270  const RBeginFunctionReturnsEmptyPtr dd{};271  assert(std::ranges::rbegin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic272  assert(std::ranges::crbegin(d) == &d.x);273  assert(std::ranges::rbegin(dd) == &dd.x);274  assert(std::ranges::crbegin(dd) == &dd.x);275 276  RBeginFunctionWithDataMember e{};277  const RBeginFunctionWithDataMember ee{};278  assert(std::ranges::rbegin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic279  assert(std::ranges::rbegin(ee) == &ee.x);280  assert(std::ranges::crbegin(e) == &e.x);281  assert(std::ranges::crbegin(ee) == &ee.x);282 283  RBeginFunctionWithPrivateBeginMember f{};284  const RBeginFunctionWithPrivateBeginMember ff{};285  assert(std::ranges::rbegin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic286  assert(std::ranges::crbegin(f) == &f.y);287  assert(std::ranges::rbegin(ff) == &ff.y);288  assert(std::ranges::crbegin(ff) == &ff.y);289 290  return true;291}292 293 294struct MemberBeginEnd {295  int b, e;296  char cb, ce;297  constexpr bidirectional_iterator<int*> begin() { return bidirectional_iterator<int*>(&b); }298  constexpr bidirectional_iterator<int*> end() { return bidirectional_iterator<int*>(&e); }299  constexpr bidirectional_iterator<const char*> begin() const { return bidirectional_iterator<const char*>(&cb); }300  constexpr bidirectional_iterator<const char*> end() const { return bidirectional_iterator<const char*>(&ce); }301};302static_assert( std::is_invocable_v<RangeRBeginT, MemberBeginEnd&>);303static_assert( std::is_invocable_v<RangeRBeginT, MemberBeginEnd const&>);304static_assert( std::is_invocable_v<RangeCRBeginT, MemberBeginEnd const&>);305 306struct FunctionBeginEnd {307  int b, e;308  char cb, ce;309  friend constexpr bidirectional_iterator<int*> begin(FunctionBeginEnd& v) {310    return bidirectional_iterator<int*>(&v.b);311  }312  friend constexpr bidirectional_iterator<int*> end(FunctionBeginEnd& v) { return bidirectional_iterator<int*>(&v.e); }313  friend constexpr bidirectional_iterator<const char*> begin(const FunctionBeginEnd& v) {314    return bidirectional_iterator<const char*>(&v.cb);315  }316  friend constexpr bidirectional_iterator<const char*> end(const FunctionBeginEnd& v) {317    return bidirectional_iterator<const char*>(&v.ce);318  }319};320static_assert( std::is_invocable_v<RangeRBeginT, FunctionBeginEnd&>);321static_assert( std::is_invocable_v<RangeRBeginT, FunctionBeginEnd const&>);322static_assert( std::is_invocable_v<RangeCRBeginT, FunctionBeginEnd const&>);323 324struct MemberBeginFunctionEnd {325  int b, e;326  char cb, ce;327  constexpr bidirectional_iterator<int*> begin() { return bidirectional_iterator<int*>(&b); }328  friend constexpr bidirectional_iterator<int*> end(MemberBeginFunctionEnd& v) {329    return bidirectional_iterator<int*>(&v.e);330  }331  constexpr bidirectional_iterator<const char*> begin() const { return bidirectional_iterator<const char*>(&cb); }332  friend constexpr bidirectional_iterator<const char*> end(const MemberBeginFunctionEnd& v) {333    return bidirectional_iterator<const char*>(&v.ce);334  }335};336static_assert( std::is_invocable_v<RangeRBeginT, MemberBeginFunctionEnd&>);337static_assert( std::is_invocable_v<RangeRBeginT, MemberBeginFunctionEnd const&>);338static_assert( std::is_invocable_v<RangeCRBeginT, MemberBeginFunctionEnd const&>);339 340struct FunctionBeginMemberEnd {341  int b, e;342  char cb, ce;343  friend constexpr bidirectional_iterator<int*> begin(FunctionBeginMemberEnd& v) {344    return bidirectional_iterator<int*>(&v.b);345  }346  constexpr bidirectional_iterator<int*> end() { return bidirectional_iterator<int*>(&e); }347  friend constexpr bidirectional_iterator<const char*> begin(const FunctionBeginMemberEnd& v) {348    return bidirectional_iterator<const char*>(&v.cb);349  }350  constexpr bidirectional_iterator<const char*> end() const { return bidirectional_iterator<const char*>(&ce); }351};352static_assert( std::is_invocable_v<RangeRBeginT, FunctionBeginMemberEnd&>);353static_assert( std::is_invocable_v<RangeRBeginT, FunctionBeginMemberEnd const&>);354static_assert( std::is_invocable_v<RangeCRBeginT, FunctionBeginMemberEnd const&>);355 356struct MemberBeginEndDifferentTypes {357  bidirectional_iterator<int*> begin();358  bidirectional_iterator<const int*> end();359};360static_assert(!std::is_invocable_v<RangeRBeginT, MemberBeginEndDifferentTypes&>);361static_assert(!std::is_invocable_v<RangeCRBeginT, MemberBeginEndDifferentTypes&>);362 363struct FunctionBeginEndDifferentTypes {364  friend bidirectional_iterator<int*> begin(FunctionBeginEndDifferentTypes&);365  friend bidirectional_iterator<const int*> end(FunctionBeginEndDifferentTypes&);366};367static_assert(!std::is_invocable_v<RangeRBeginT, FunctionBeginEndDifferentTypes&>);368static_assert(!std::is_invocable_v<RangeCRBeginT, FunctionBeginEndDifferentTypes&>);369 370struct MemberBeginEndForwardIterators {371  forward_iterator<int*> begin();372  forward_iterator<int*> end();373};374static_assert(!std::is_invocable_v<RangeRBeginT, MemberBeginEndForwardIterators&>);375static_assert(!std::is_invocable_v<RangeCRBeginT, MemberBeginEndForwardIterators&>);376 377struct FunctionBeginEndForwardIterators {378  friend forward_iterator<int*> begin(FunctionBeginEndForwardIterators&);379  friend forward_iterator<int*> end(FunctionBeginEndForwardIterators&);380};381static_assert(!std::is_invocable_v<RangeRBeginT, FunctionBeginEndForwardIterators&>);382static_assert(!std::is_invocable_v<RangeCRBeginT, FunctionBeginEndForwardIterators&>);383 384struct MemberBeginOnly {385  bidirectional_iterator<int*> begin() const;386};387static_assert(!std::is_invocable_v<RangeRBeginT, MemberBeginOnly&>);388static_assert(!std::is_invocable_v<RangeCRBeginT, MemberBeginOnly&>);389 390struct FunctionBeginOnly {391  friend bidirectional_iterator<int*> begin(FunctionBeginOnly&);392};393static_assert(!std::is_invocable_v<RangeRBeginT, FunctionBeginOnly&>);394static_assert(!std::is_invocable_v<RangeCRBeginT, FunctionBeginOnly&>);395 396struct MemberEndOnly {397  bidirectional_iterator<int*> end() const;398};399static_assert(!std::is_invocable_v<RangeRBeginT, MemberEndOnly&>);400static_assert(!std::is_invocable_v<RangeCRBeginT, MemberEndOnly&>);401 402struct FunctionEndOnly {403  friend bidirectional_iterator<int*> end(FunctionEndOnly&);404};405static_assert(!std::is_invocable_v<RangeRBeginT, FunctionEndOnly&>);406static_assert(!std::is_invocable_v<RangeCRBeginT, FunctionEndOnly&>);407 408// Make sure there is no clash between the following cases:409// - the case that handles classes defining member `rbegin` and `rend` functions;410// - the case that handles classes defining `begin` and `end` functions returning reversible iterators.411struct MemberBeginAndRBegin {412  int* begin() const;413  int* end() const;414  int* rbegin() const;415  int* rend() const;416};417static_assert( std::is_invocable_v<RangeRBeginT, MemberBeginAndRBegin&>);418static_assert( std::is_invocable_v<RangeCRBeginT, MemberBeginAndRBegin&>);419static_assert( std::same_as<std::invoke_result_t<RangeRBeginT, MemberBeginAndRBegin&>, int*>);420static_assert( std::same_as<std::invoke_result_t<RangeCRBeginT, MemberBeginAndRBegin&>, int*>);421 422constexpr bool testBeginEnd() {423  MemberBeginEnd a{};424  const MemberBeginEnd aa{};425  assert(base(std::ranges::rbegin(a).base()) == &a.e);426  assert(base(std::ranges::crbegin(a).base()) == &a.ce);427  assert(base(std::ranges::rbegin(aa).base()) == &aa.ce);428  assert(base(std::ranges::crbegin(aa).base()) == &aa.ce);429 430  FunctionBeginEnd b{};431  const FunctionBeginEnd bb{};432  assert(base(std::ranges::rbegin(b).base()) == &b.e);433  assert(base(std::ranges::crbegin(b).base()) == &b.ce);434  assert(base(std::ranges::rbegin(bb).base()) == &bb.ce);435  assert(base(std::ranges::crbegin(bb).base()) == &bb.ce);436 437  MemberBeginFunctionEnd c{};438  const MemberBeginFunctionEnd cc{};439  assert(base(std::ranges::rbegin(c).base()) == &c.e);440  assert(base(std::ranges::crbegin(c).base()) == &c.ce);441  assert(base(std::ranges::rbegin(cc).base()) == &cc.ce);442  assert(base(std::ranges::crbegin(cc).base()) == &cc.ce);443 444  FunctionBeginMemberEnd d{};445  const FunctionBeginMemberEnd dd{};446  assert(base(std::ranges::rbegin(d).base()) == &d.e);447  assert(base(std::ranges::crbegin(d).base()) == &d.ce);448  assert(base(std::ranges::rbegin(dd).base()) == &dd.ce);449  assert(base(std::ranges::crbegin(dd).base()) == &dd.ce);450 451  return true;452}453 454 455ASSERT_NOEXCEPT(std::ranges::rbegin(std::declval<int (&)[10]>()));456ASSERT_NOEXCEPT(std::ranges::crbegin(std::declval<int (&)[10]>()));457 458struct NoThrowMemberRBegin {459  ThrowingIterator<int> rbegin() const noexcept; // auto(t.rbegin()) doesn't throw460} ntmb;461static_assert(noexcept(std::ranges::rbegin(ntmb)));462static_assert(noexcept(std::ranges::crbegin(ntmb)));463 464struct NoThrowADLRBegin {465  friend ThrowingIterator<int> rbegin(NoThrowADLRBegin&) noexcept;  // auto(rbegin(t)) doesn't throw466  friend ThrowingIterator<int> rbegin(const NoThrowADLRBegin&) noexcept;467} ntab;468static_assert(noexcept(std::ranges::rbegin(ntab)));469static_assert(noexcept(std::ranges::crbegin(ntab)));470 471struct NoThrowMemberRBeginReturnsRef {472  ThrowingIterator<int>& rbegin() const noexcept; // auto(t.rbegin()) may throw473} ntmbrr;474static_assert(!noexcept(std::ranges::rbegin(ntmbrr)));475static_assert(!noexcept(std::ranges::crbegin(ntmbrr)));476 477struct RBeginReturnsArrayRef {478    auto rbegin() const noexcept -> int(&)[10];479} brar;480static_assert(noexcept(std::ranges::rbegin(brar)));481static_assert(noexcept(std::ranges::crbegin(brar)));482 483struct NoThrowBeginThrowingEnd {484  int* begin() const noexcept;485  int* end() const;486} ntbte;487static_assert(!noexcept(std::ranges::rbegin(ntbte)));488static_assert(!noexcept(std::ranges::crbegin(ntbte)));489 490struct NoThrowEndThrowingBegin {491  int* begin() const;492  int* end() const noexcept;493} ntetb;494static_assert(noexcept(std::ranges::rbegin(ntetb)));495static_assert(noexcept(std::ranges::crbegin(ntetb)));496 497// Test ADL-proofing.498struct Incomplete;499template<class T> struct Holder { T t; };500static_assert(!std::is_invocable_v<RangeRBeginT, Holder<Incomplete>*>);501static_assert(!std::is_invocable_v<RangeRBeginT, Holder<Incomplete>*&>);502static_assert(!std::is_invocable_v<RangeCRBeginT, Holder<Incomplete>*>);503static_assert(!std::is_invocable_v<RangeCRBeginT, Holder<Incomplete>*&>);504 505int main(int, char**) {506  static_assert(testReturnTypes());507 508  testArray();509  static_assert(testArray());510 511  testRBeginMember();512  static_assert(testRBeginMember());513 514  testRBeginFunction();515  static_assert(testRBeginFunction());516 517  testBeginEnd();518  static_assert(testBeginEnd());519 520  return 0;521}522