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