xref: /llvm-project/libcxx/test/std/ranges/range.access/end.pass.cpp (revision 12978b3e23a2766732595391c193e5631f40a3db)
16842f52aSArthur O'Dwyer //===----------------------------------------------------------------------===//
26842f52aSArthur O'Dwyer //
36842f52aSArthur O'Dwyer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46842f52aSArthur O'Dwyer // See https://llvm.org/LICENSE.txt for license information.
56842f52aSArthur O'Dwyer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66842f52aSArthur O'Dwyer //
76842f52aSArthur O'Dwyer //===----------------------------------------------------------------------===//
86842f52aSArthur O'Dwyer 
96842f52aSArthur O'Dwyer // UNSUPPORTED: c++03, c++11, c++14, c++17
106842f52aSArthur O'Dwyer 
116842f52aSArthur O'Dwyer // std::ranges::end
12502e5df0SArthur O'Dwyer // std::ranges::cend
136842f52aSArthur O'Dwyer 
146842f52aSArthur O'Dwyer #include <ranges>
156842f52aSArthur O'Dwyer 
166842f52aSArthur O'Dwyer #include <cassert>
17e1e17a64SKonstantin Varlamov #include <utility>
186842f52aSArthur O'Dwyer #include "test_macros.h"
196842f52aSArthur O'Dwyer #include "test_iterators.h"
206842f52aSArthur O'Dwyer 
21502e5df0SArthur O'Dwyer using RangeEndT = decltype(std::ranges::end);
22502e5df0SArthur O'Dwyer using RangeCEndT = decltype(std::ranges::cend);
236842f52aSArthur O'Dwyer 
246842f52aSArthur O'Dwyer static int globalBuff[8];
256842f52aSArthur O'Dwyer 
266842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, int (&&)[]>);
276842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, int (&)[]>);
286842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, int (&&)[10]>);
296842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeEndT, int (&)[10]>);
30e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeCEndT, int (&&)[]>);
31e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeCEndT, int (&)[]>);
32e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeCEndT, int (&&)[10]>);
33e1e17a64SKonstantin Varlamov static_assert( std::is_invocable_v<RangeCEndT, int (&)[10]>);
346842f52aSArthur O'Dwyer 
356842f52aSArthur O'Dwyer struct Incomplete;
366842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, Incomplete(&&)[]>);
376842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, Incomplete(&&)[42]>);
386842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, Incomplete(&&)[]>);
396842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, Incomplete(&&)[42]>);
406842f52aSArthur O'Dwyer 
416842f52aSArthur O'Dwyer struct EndMember {
426842f52aSArthur O'Dwyer   int x;
43a70fe039SArthur O'Dwyer   const int *begin() const;
endEndMember446842f52aSArthur O'Dwyer   constexpr const int *end() const { return &x; }
456842f52aSArthur O'Dwyer };
466842f52aSArthur O'Dwyer 
476842f52aSArthur O'Dwyer // Ensure that we can't call with rvalues with borrowing disabled.
486842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeEndT, EndMember &>);
496842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, EndMember &&>);
50a70fe039SArthur O'Dwyer static_assert( std::is_invocable_v<RangeEndT, EndMember const&>);
51a70fe039SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, EndMember const&&>);
526842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCEndT, EndMember &>);
53a70fe039SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, EndMember &&>);
546842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCEndT, EndMember const&>);
55a70fe039SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, EndMember const&&>);
566842f52aSArthur O'Dwyer 
testReturnTypes()57502e5df0SArthur O'Dwyer constexpr bool testReturnTypes() {
58502e5df0SArthur O'Dwyer   {
59502e5df0SArthur O'Dwyer     int *x[2];
60502e5df0SArthur O'Dwyer     ASSERT_SAME_TYPE(decltype(std::ranges::end(x)), int**);
61502e5df0SArthur O'Dwyer     ASSERT_SAME_TYPE(decltype(std::ranges::cend(x)), int* const*);
62502e5df0SArthur O'Dwyer   }
63502e5df0SArthur O'Dwyer   {
64502e5df0SArthur O'Dwyer     int x[2][2];
65502e5df0SArthur O'Dwyer     ASSERT_SAME_TYPE(decltype(std::ranges::end(x)), int(*)[2]);
66502e5df0SArthur O'Dwyer     ASSERT_SAME_TYPE(decltype(std::ranges::cend(x)), const int(*)[2]);
67502e5df0SArthur O'Dwyer   }
68502e5df0SArthur O'Dwyer   {
69502e5df0SArthur O'Dwyer     struct Different {
70502e5df0SArthur O'Dwyer       char *begin();
71502e5df0SArthur O'Dwyer       sentinel_wrapper<char*>& end();
72502e5df0SArthur O'Dwyer       short *begin() const;
73502e5df0SArthur O'Dwyer       sentinel_wrapper<short*>& end() const;
74502e5df0SArthur O'Dwyer     } x;
75502e5df0SArthur O'Dwyer     ASSERT_SAME_TYPE(decltype(std::ranges::end(x)), sentinel_wrapper<char*>);
76502e5df0SArthur O'Dwyer     ASSERT_SAME_TYPE(decltype(std::ranges::cend(x)), sentinel_wrapper<short*>);
77502e5df0SArthur O'Dwyer   }
78502e5df0SArthur O'Dwyer   return true;
79502e5df0SArthur O'Dwyer }
80502e5df0SArthur O'Dwyer 
testArray()816842f52aSArthur O'Dwyer constexpr bool testArray() {
826842f52aSArthur O'Dwyer   int a[2];
836842f52aSArthur O'Dwyer   assert(std::ranges::end(a) == a + 2);
846842f52aSArthur O'Dwyer   assert(std::ranges::cend(a) == a + 2);
856842f52aSArthur O'Dwyer 
866842f52aSArthur O'Dwyer   int b[2][2];
876842f52aSArthur O'Dwyer   assert(std::ranges::end(b) == b + 2);
886842f52aSArthur O'Dwyer   assert(std::ranges::cend(b) == b + 2);
896842f52aSArthur O'Dwyer 
906842f52aSArthur O'Dwyer   EndMember c[2];
916842f52aSArthur O'Dwyer   assert(std::ranges::end(c) == c + 2);
926842f52aSArthur O'Dwyer   assert(std::ranges::cend(c) == c + 2);
936842f52aSArthur O'Dwyer 
946842f52aSArthur O'Dwyer   return true;
956842f52aSArthur O'Dwyer }
966842f52aSArthur O'Dwyer 
976842f52aSArthur O'Dwyer struct EndMemberReturnsInt {
986842f52aSArthur O'Dwyer   int begin() const;
996842f52aSArthur O'Dwyer   int end() const;
1006842f52aSArthur O'Dwyer };
1016842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, EndMemberReturnsInt const&>);
1026842f52aSArthur O'Dwyer 
1036842f52aSArthur O'Dwyer struct EndMemberReturnsVoidPtr {
1046842f52aSArthur O'Dwyer   const void *begin() const;
1056842f52aSArthur O'Dwyer   const void *end() const;
1066842f52aSArthur O'Dwyer };
1076842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, EndMemberReturnsVoidPtr const&>);
1086842f52aSArthur O'Dwyer 
1096842f52aSArthur O'Dwyer struct PtrConvertible {
1106842f52aSArthur O'Dwyer   operator int*() const;
1116842f52aSArthur O'Dwyer };
1126842f52aSArthur O'Dwyer struct PtrConvertibleEndMember {
1136842f52aSArthur O'Dwyer   PtrConvertible begin() const;
1146842f52aSArthur O'Dwyer   PtrConvertible end() const;
1156842f52aSArthur O'Dwyer };
1166842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, PtrConvertibleEndMember const&>);
1176842f52aSArthur O'Dwyer 
1186842f52aSArthur O'Dwyer struct NoBeginMember {
1196842f52aSArthur O'Dwyer   constexpr const int *end();
1206842f52aSArthur O'Dwyer };
1216842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, NoBeginMember const&>);
1226842f52aSArthur O'Dwyer 
1236842f52aSArthur O'Dwyer struct NonConstEndMember {
1246842f52aSArthur O'Dwyer   int x;
beginNonConstEndMember1256842f52aSArthur O'Dwyer   constexpr int *begin() { return nullptr; }
endNonConstEndMember1266842f52aSArthur O'Dwyer   constexpr int *end() { return &x; }
1276842f52aSArthur O'Dwyer };
1286842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeEndT,  NonConstEndMember &>);
1296842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT,  NonConstEndMember const&>);
1306842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, NonConstEndMember &>);
1316842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, NonConstEndMember const&>);
1326842f52aSArthur O'Dwyer 
1336842f52aSArthur O'Dwyer struct EnabledBorrowingEndMember {
beginEnabledBorrowingEndMember1346842f52aSArthur O'Dwyer   constexpr int *begin() const { return nullptr; }
endEnabledBorrowingEndMember1356842f52aSArthur O'Dwyer   constexpr int *end() const { return &globalBuff[0]; }
1366842f52aSArthur O'Dwyer };
1376842f52aSArthur O'Dwyer 
1386842f52aSArthur O'Dwyer template<>
1396842f52aSArthur O'Dwyer inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingEndMember> = true;
1406842f52aSArthur O'Dwyer 
141e1e17a64SKonstantin Varlamov struct EndMemberFunction {
142e1e17a64SKonstantin Varlamov   int x;
beginEndMemberFunction143e1e17a64SKonstantin Varlamov   constexpr const int *begin() const { return nullptr; }
endEndMemberFunction144e1e17a64SKonstantin Varlamov   constexpr const int *end() const { return &x; }
145e1e17a64SKonstantin Varlamov   friend constexpr int *end(EndMemberFunction const&);
146e1e17a64SKonstantin Varlamov };
147e1e17a64SKonstantin Varlamov 
148e1e17a64SKonstantin Varlamov struct Empty { };
149e1e17a64SKonstantin Varlamov struct EmptyEndMember {
150e1e17a64SKonstantin Varlamov   Empty begin() const;
151e1e17a64SKonstantin Varlamov   Empty end() const;
152e1e17a64SKonstantin Varlamov };
153e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeEndT, EmptyEndMember const&>);
154e1e17a64SKonstantin Varlamov 
155e1e17a64SKonstantin Varlamov struct EmptyPtrEndMember {
156e1e17a64SKonstantin Varlamov   Empty x;
beginEmptyPtrEndMember157e1e17a64SKonstantin Varlamov   constexpr const Empty *begin() const { return nullptr; }
endEmptyPtrEndMember158e1e17a64SKonstantin Varlamov   constexpr const Empty *end() const { return &x; }
159e1e17a64SKonstantin Varlamov };
160e1e17a64SKonstantin Varlamov 
testEndMember()1616842f52aSArthur O'Dwyer constexpr bool testEndMember() {
1626842f52aSArthur O'Dwyer   EndMember a;
1636842f52aSArthur O'Dwyer   assert(std::ranges::end(a) == &a.x);
1646842f52aSArthur O'Dwyer   assert(std::ranges::cend(a) == &a.x);
1656842f52aSArthur O'Dwyer 
1666842f52aSArthur O'Dwyer   NonConstEndMember b;
1676842f52aSArthur O'Dwyer   assert(std::ranges::end(b) == &b.x);
168502e5df0SArthur O'Dwyer   static_assert(!std::is_invocable_v<RangeCEndT, decltype((b))>);
1696842f52aSArthur O'Dwyer 
1706842f52aSArthur O'Dwyer   EnabledBorrowingEndMember c;
1716842f52aSArthur O'Dwyer   assert(std::ranges::end(std::move(c)) == &globalBuff[0]);
172502e5df0SArthur O'Dwyer   assert(std::ranges::cend(std::move(c)) == &globalBuff[0]);
1736842f52aSArthur O'Dwyer 
1746842f52aSArthur O'Dwyer   EndMemberFunction d;
1756842f52aSArthur O'Dwyer   assert(std::ranges::end(d) == &d.x);
1766842f52aSArthur O'Dwyer   assert(std::ranges::cend(d) == &d.x);
1776842f52aSArthur O'Dwyer 
1786842f52aSArthur O'Dwyer   EmptyPtrEndMember e;
1796842f52aSArthur O'Dwyer   assert(std::ranges::end(e) == &e.x);
1806842f52aSArthur O'Dwyer   assert(std::ranges::cend(e) == &e.x);
1816842f52aSArthur O'Dwyer 
1826842f52aSArthur O'Dwyer   return true;
1836842f52aSArthur O'Dwyer }
1846842f52aSArthur O'Dwyer 
1856842f52aSArthur O'Dwyer struct EndFunction {
1866842f52aSArthur O'Dwyer   int x;
begin(EndFunction const &)1876842f52aSArthur O'Dwyer   friend constexpr const int *begin(EndFunction const&) { return nullptr; }
end(EndFunction const & bf)1886842f52aSArthur O'Dwyer   friend constexpr const int *end(EndFunction const& bf) { return &bf.x; }
1896842f52aSArthur O'Dwyer };
1906842f52aSArthur O'Dwyer 
1916842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>);
1926842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
1936842f52aSArthur O'Dwyer 
1946842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeEndT,  EndFunction const&>);
1956842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT,  EndFunction &&>);
196*12978b3eSJakub Mazurkiewicz static_assert(std::is_invocable_v<RangeEndT, EndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
1976842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCEndT, EndFunction const&>);
1986842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCEndT, EndFunction &>);
1996842f52aSArthur O'Dwyer 
200e1e17a64SKonstantin Varlamov struct EndFunctionReturnsInt {
201e1e17a64SKonstantin Varlamov   friend constexpr int begin(EndFunctionReturnsInt const&);
202e1e17a64SKonstantin Varlamov   friend constexpr int end(EndFunctionReturnsInt const&);
2036842f52aSArthur O'Dwyer };
204e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsInt const&>);
2056842f52aSArthur O'Dwyer 
206e1e17a64SKonstantin Varlamov struct EndFunctionReturnsVoidPtr {
207e1e17a64SKonstantin Varlamov   friend constexpr void *begin(EndFunctionReturnsVoidPtr const&);
208e1e17a64SKonstantin Varlamov   friend constexpr void *end(EndFunctionReturnsVoidPtr const&);
2096842f52aSArthur O'Dwyer };
210e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsVoidPtr const&>);
211e1e17a64SKonstantin Varlamov 
212e1e17a64SKonstantin Varlamov struct EndFunctionReturnsEmpty {
213e1e17a64SKonstantin Varlamov   friend constexpr Empty begin(EndFunctionReturnsEmpty const&);
214e1e17a64SKonstantin Varlamov   friend constexpr Empty end(EndFunctionReturnsEmpty const&);
215e1e17a64SKonstantin Varlamov };
216e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsEmpty const&>);
217e1e17a64SKonstantin Varlamov 
218e1e17a64SKonstantin Varlamov struct EndFunctionReturnsPtrConvertible {
219e1e17a64SKonstantin Varlamov   friend constexpr PtrConvertible begin(EndFunctionReturnsPtrConvertible const&);
220e1e17a64SKonstantin Varlamov   friend constexpr PtrConvertible end(EndFunctionReturnsPtrConvertible const&);
221e1e17a64SKonstantin Varlamov };
222e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeEndT, EndFunctionReturnsPtrConvertible const&>);
223e1e17a64SKonstantin Varlamov 
224e1e17a64SKonstantin Varlamov struct NoBeginFunction {
225e1e17a64SKonstantin Varlamov   friend constexpr const int *end(NoBeginFunction const&);
226e1e17a64SKonstantin Varlamov };
227e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeEndT, NoBeginFunction const&>);
228e1e17a64SKonstantin Varlamov 
229e1e17a64SKonstantin Varlamov struct EndFunctionByValue {
begin(EndFunctionByValue)230e1e17a64SKonstantin Varlamov   friend constexpr int *begin(EndFunctionByValue) { return nullptr; }
end(EndFunctionByValue)231e1e17a64SKonstantin Varlamov   friend constexpr int *end(EndFunctionByValue) { return &globalBuff[1]; }
232e1e17a64SKonstantin Varlamov };
233e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeCEndT, EndFunctionByValue>);
234e1e17a64SKonstantin Varlamov 
235e1e17a64SKonstantin Varlamov struct EndFunctionEnabledBorrowing {
begin(EndFunctionEnabledBorrowing)236e1e17a64SKonstantin Varlamov   friend constexpr int *begin(EndFunctionEnabledBorrowing) { return nullptr; }
end(EndFunctionEnabledBorrowing)237e1e17a64SKonstantin Varlamov   friend constexpr int *end(EndFunctionEnabledBorrowing) { return &globalBuff[2]; }
238e1e17a64SKonstantin Varlamov };
239e1e17a64SKonstantin Varlamov template<>
240e1e17a64SKonstantin Varlamov inline constexpr bool std::ranges::enable_borrowed_range<EndFunctionEnabledBorrowing> = true;
2416842f52aSArthur O'Dwyer 
2426842f52aSArthur O'Dwyer struct EndFunctionReturnsEmptyPtr {
2436842f52aSArthur O'Dwyer   Empty x;
begin(EndFunctionReturnsEmptyPtr const &)2446842f52aSArthur O'Dwyer   friend constexpr const Empty *begin(EndFunctionReturnsEmptyPtr const&) { return nullptr; }
end(EndFunctionReturnsEmptyPtr const & bf)2456842f52aSArthur O'Dwyer   friend constexpr const Empty *end(EndFunctionReturnsEmptyPtr const& bf) { return &bf.x; }
2466842f52aSArthur O'Dwyer };
2476842f52aSArthur O'Dwyer 
248e1e17a64SKonstantin Varlamov struct EndFunctionWithDataMember {
249e1e17a64SKonstantin Varlamov   int x;
250e1e17a64SKonstantin Varlamov   int end;
begin(EndFunctionWithDataMember const &)251e1e17a64SKonstantin Varlamov   friend constexpr const int *begin(EndFunctionWithDataMember const&) { return nullptr; }
end(EndFunctionWithDataMember const & bf)252e1e17a64SKonstantin Varlamov   friend constexpr const int *end(EndFunctionWithDataMember const& bf) { return &bf.x; }
2536842f52aSArthur O'Dwyer };
2546842f52aSArthur O'Dwyer 
255e1e17a64SKonstantin Varlamov struct EndFunctionWithPrivateEndMember {
256e1e17a64SKonstantin Varlamov   int y;
begin(EndFunctionWithPrivateEndMember const &)257e1e17a64SKonstantin Varlamov   friend constexpr const int *begin(EndFunctionWithPrivateEndMember const&) { return nullptr; }
end(EndFunctionWithPrivateEndMember const & bf)258e1e17a64SKonstantin Varlamov   friend constexpr const int *end(EndFunctionWithPrivateEndMember const& bf) { return &bf.y; }
259e1e17a64SKonstantin Varlamov private:
260e1e17a64SKonstantin Varlamov   const int *end() const;
2616842f52aSArthur O'Dwyer };
2626842f52aSArthur O'Dwyer 
2636842f52aSArthur O'Dwyer struct BeginMemberEndFunction {
2646842f52aSArthur O'Dwyer   int x;
beginBeginMemberEndFunction2656842f52aSArthur O'Dwyer   constexpr const int *begin() const { return nullptr; }
end(BeginMemberEndFunction const & bf)2666842f52aSArthur O'Dwyer   friend constexpr const int *end(BeginMemberEndFunction const& bf) { return &bf.x; }
2676842f52aSArthur O'Dwyer };
2686842f52aSArthur O'Dwyer 
testEndFunction()2696842f52aSArthur O'Dwyer constexpr bool testEndFunction() {
2706842f52aSArthur O'Dwyer   const EndFunction a{};
2716842f52aSArthur O'Dwyer   assert(std::ranges::end(a) == &a.x);
272502e5df0SArthur O'Dwyer   assert(std::ranges::cend(a) == &a.x);
2736842f52aSArthur O'Dwyer   EndFunction aa{};
274*12978b3eSJakub Mazurkiewicz   assert(std::ranges::end(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
2756842f52aSArthur O'Dwyer   assert(std::ranges::cend(aa) == &aa.x);
2766842f52aSArthur O'Dwyer 
2776842f52aSArthur O'Dwyer   EndFunctionByValue b;
2786842f52aSArthur O'Dwyer   assert(std::ranges::end(b) == &globalBuff[1]);
2796842f52aSArthur O'Dwyer   assert(std::ranges::cend(b) == &globalBuff[1]);
2806842f52aSArthur O'Dwyer 
2816842f52aSArthur O'Dwyer   EndFunctionEnabledBorrowing c;
2826842f52aSArthur O'Dwyer   assert(std::ranges::end(std::move(c)) == &globalBuff[2]);
283502e5df0SArthur O'Dwyer   assert(std::ranges::cend(std::move(c)) == &globalBuff[2]);
2846842f52aSArthur O'Dwyer 
2856842f52aSArthur O'Dwyer   const EndFunctionReturnsEmptyPtr d{};
2866842f52aSArthur O'Dwyer   assert(std::ranges::end(d) == &d.x);
287502e5df0SArthur O'Dwyer   assert(std::ranges::cend(d) == &d.x);
2886842f52aSArthur O'Dwyer   EndFunctionReturnsEmptyPtr dd{};
289*12978b3eSJakub Mazurkiewicz   assert(std::ranges::end(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
2906842f52aSArthur O'Dwyer   assert(std::ranges::cend(dd) == &dd.x);
2916842f52aSArthur O'Dwyer 
2926842f52aSArthur O'Dwyer   const EndFunctionWithDataMember e{};
2936842f52aSArthur O'Dwyer   assert(std::ranges::end(e) == &e.x);
294502e5df0SArthur O'Dwyer   assert(std::ranges::cend(e) == &e.x);
2956842f52aSArthur O'Dwyer   EndFunctionWithDataMember ee{};
296*12978b3eSJakub Mazurkiewicz   assert(std::ranges::end(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
2976842f52aSArthur O'Dwyer   assert(std::ranges::cend(ee) == &ee.x);
2986842f52aSArthur O'Dwyer 
2996842f52aSArthur O'Dwyer   const EndFunctionWithPrivateEndMember f{};
3006842f52aSArthur O'Dwyer   assert(std::ranges::end(f) == &f.y);
301502e5df0SArthur O'Dwyer   assert(std::ranges::cend(f) == &f.y);
3026842f52aSArthur O'Dwyer   EndFunctionWithPrivateEndMember ff{};
303*12978b3eSJakub Mazurkiewicz   assert(std::ranges::end(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
3046842f52aSArthur O'Dwyer   assert(std::ranges::cend(ff) == &ff.y);
3056842f52aSArthur O'Dwyer 
3066842f52aSArthur O'Dwyer   const BeginMemberEndFunction g{};
3076842f52aSArthur O'Dwyer   assert(std::ranges::end(g) == &g.x);
308502e5df0SArthur O'Dwyer   assert(std::ranges::cend(g) == &g.x);
3096842f52aSArthur O'Dwyer   BeginMemberEndFunction gg{};
310*12978b3eSJakub Mazurkiewicz   assert(std::ranges::end(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
3116842f52aSArthur O'Dwyer   assert(std::ranges::cend(gg) == &gg.x);
3126842f52aSArthur O'Dwyer 
3136842f52aSArthur O'Dwyer   return true;
3146842f52aSArthur O'Dwyer }
3156842f52aSArthur O'Dwyer 
3166842f52aSArthur O'Dwyer 
3176842f52aSArthur O'Dwyer ASSERT_NOEXCEPT(std::ranges::end(std::declval<int (&)[10]>()));
3186842f52aSArthur O'Dwyer ASSERT_NOEXCEPT(std::ranges::cend(std::declval<int (&)[10]>()));
3196842f52aSArthur O'Dwyer 
3206842f52aSArthur O'Dwyer struct NoThrowMemberEnd {
3216842f52aSArthur O'Dwyer   ThrowingIterator<int> begin() const;
3226842f52aSArthur O'Dwyer   ThrowingIterator<int> end() const noexcept; // auto(t.end()) doesn't throw
3236842f52aSArthur O'Dwyer } ntme;
3246842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::end(ntme)));
3256842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::cend(ntme)));
3266842f52aSArthur O'Dwyer 
3276842f52aSArthur O'Dwyer struct NoThrowADLEnd {
3286842f52aSArthur O'Dwyer   ThrowingIterator<int> begin() const;
3296842f52aSArthur O'Dwyer   friend ThrowingIterator<int> end(NoThrowADLEnd&) noexcept;  // auto(end(t)) doesn't throw
3306842f52aSArthur O'Dwyer   friend ThrowingIterator<int> end(const NoThrowADLEnd&) noexcept;
3316842f52aSArthur O'Dwyer } ntae;
3326842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::end(ntae)));
3336842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::cend(ntae)));
3346842f52aSArthur O'Dwyer 
3356842f52aSArthur O'Dwyer struct NoThrowMemberEndReturnsRef {
3366842f52aSArthur O'Dwyer   ThrowingIterator<int> begin() const;
3376842f52aSArthur O'Dwyer   ThrowingIterator<int>& end() const noexcept; // auto(t.end()) may throw
3386842f52aSArthur O'Dwyer } ntmerr;
3396842f52aSArthur O'Dwyer static_assert(!noexcept(std::ranges::end(ntmerr)));
3406842f52aSArthur O'Dwyer static_assert(!noexcept(std::ranges::cend(ntmerr)));
3416842f52aSArthur O'Dwyer 
3426842f52aSArthur O'Dwyer struct EndReturnsArrayRef {
3436842f52aSArthur O'Dwyer     auto begin() const noexcept -> int(&)[10];
3446842f52aSArthur O'Dwyer     auto end() const noexcept -> int(&)[10];
3456842f52aSArthur O'Dwyer } erar;
3466842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::end(erar)));
3476842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::cend(erar)));
3486842f52aSArthur O'Dwyer 
34985073836SArthur O'Dwyer // Test ADL-proofing.
35085073836SArthur O'Dwyer struct Incomplete;
35185073836SArthur O'Dwyer template<class T> struct Holder { T t; };
35285073836SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, Holder<Incomplete>*>);
3539be193bcSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeEndT, Holder<Incomplete>*&>);
35485073836SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, Holder<Incomplete>*>);
3559be193bcSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCEndT, Holder<Incomplete>*&>);
35685073836SArthur O'Dwyer 
main(int,char **)3576842f52aSArthur O'Dwyer int main(int, char**) {
358502e5df0SArthur O'Dwyer   static_assert(testReturnTypes());
359502e5df0SArthur O'Dwyer 
3606842f52aSArthur O'Dwyer   testArray();
3616842f52aSArthur O'Dwyer   static_assert(testArray());
3626842f52aSArthur O'Dwyer 
3636842f52aSArthur O'Dwyer   testEndMember();
3646842f52aSArthur O'Dwyer   static_assert(testEndMember());
3656842f52aSArthur O'Dwyer 
3666842f52aSArthur O'Dwyer   testEndFunction();
3676842f52aSArthur O'Dwyer   static_assert(testEndFunction());
3686842f52aSArthur O'Dwyer 
3696842f52aSArthur O'Dwyer   return 0;
3706842f52aSArthur O'Dwyer }
371