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::begin
12502e5df0SArthur O'Dwyer // std::ranges::cbegin
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 RangeBeginT = decltype(std::ranges::begin);
22502e5df0SArthur O'Dwyer using RangeCBeginT = decltype(std::ranges::cbegin);
236842f52aSArthur O'Dwyer
246842f52aSArthur O'Dwyer static int globalBuff[8];
256842f52aSArthur O'Dwyer
266842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, int (&&)[10]>);
276842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeBeginT, int (&)[10]>);
286842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, int (&&)[]>);
296842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeBeginT, int (&)[]>);
30e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeCBeginT, int (&&)[10]>);
31e1e17a64SKonstantin Varlamov static_assert( std::is_invocable_v<RangeCBeginT, int (&)[10]>);
32e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeCBeginT, int (&&)[]>);
33e1e17a64SKonstantin Varlamov static_assert( std::is_invocable_v<RangeCBeginT, int (&)[]>);
346842f52aSArthur O'Dwyer
356842f52aSArthur O'Dwyer struct Incomplete;
366842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, Incomplete(&&)[]>);
37cc1d02baSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, const Incomplete(&&)[]>);
386842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, Incomplete(&&)[]>);
39cc1d02baSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, const Incomplete(&&)[]>);
40cc1d02baSArthur O'Dwyer
41cc1d02baSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, Incomplete(&&)[10]>);
42cc1d02baSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, const Incomplete(&&)[10]>);
43cc1d02baSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, Incomplete(&&)[10]>);
44cc1d02baSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, const Incomplete(&&)[10]>);
45cc1d02baSArthur O'Dwyer
46cc1d02baSArthur O'Dwyer // This case is IFNDR; we handle it SFINAE-friendly.
47cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, Incomplete(&)[]>);
48cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, const Incomplete(&)[]>);
49cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, Incomplete(&)[]>);
50cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, const Incomplete(&)[]>);
51cc1d02baSArthur O'Dwyer
52cc1d02baSArthur O'Dwyer // This case is IFNDR; we handle it SFINAE-friendly.
53cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, Incomplete(&)[10]>);
54cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeBeginT, const Incomplete(&)[10]>);
55cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, Incomplete(&)[10]>);
56cc1d02baSArthur O'Dwyer LIBCPP_STATIC_ASSERT(!std::is_invocable_v<RangeCBeginT, const Incomplete(&)[10]>);
576842f52aSArthur O'Dwyer
586842f52aSArthur O'Dwyer struct BeginMember {
596842f52aSArthur O'Dwyer int x;
beginBeginMember606842f52aSArthur O'Dwyer constexpr const int *begin() const { return &x; }
616842f52aSArthur O'Dwyer };
626842f52aSArthur O'Dwyer
636842f52aSArthur O'Dwyer // Ensure that we can't call with rvalues with borrowing disabled.
646842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeBeginT, BeginMember &>);
656842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, BeginMember &&>);
666842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeBeginT, BeginMember const&>);
676842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, BeginMember const&&>);
686842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCBeginT, BeginMember &>);
696842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, BeginMember &&>);
706842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCBeginT, BeginMember const&>);
71a70fe039SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, BeginMember const&&>);
726842f52aSArthur O'Dwyer
testReturnTypes()73502e5df0SArthur O'Dwyer constexpr bool testReturnTypes() {
74502e5df0SArthur O'Dwyer {
75502e5df0SArthur O'Dwyer int *x[2];
76502e5df0SArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::begin(x)), int**);
77502e5df0SArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::cbegin(x)), int* const*);
78502e5df0SArthur O'Dwyer }
79502e5df0SArthur O'Dwyer {
80502e5df0SArthur O'Dwyer int x[2][2];
81502e5df0SArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::begin(x)), int(*)[2]);
82502e5df0SArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::cbegin(x)), const int(*)[2]);
83502e5df0SArthur O'Dwyer }
84502e5df0SArthur O'Dwyer {
85502e5df0SArthur O'Dwyer struct Different {
86502e5df0SArthur O'Dwyer char*& begin();
87502e5df0SArthur O'Dwyer short*& begin() const;
88502e5df0SArthur O'Dwyer } x;
89502e5df0SArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::begin(x)), char*);
90502e5df0SArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::cbegin(x)), short*);
91502e5df0SArthur O'Dwyer }
92502e5df0SArthur O'Dwyer return true;
93502e5df0SArthur O'Dwyer }
94502e5df0SArthur O'Dwyer
testArray()956842f52aSArthur O'Dwyer constexpr bool testArray() {
966842f52aSArthur O'Dwyer int a[2];
976842f52aSArthur O'Dwyer assert(std::ranges::begin(a) == a);
986842f52aSArthur O'Dwyer assert(std::ranges::cbegin(a) == a);
996842f52aSArthur O'Dwyer
1006842f52aSArthur O'Dwyer int b[2][2];
1016842f52aSArthur O'Dwyer assert(std::ranges::begin(b) == b);
1026842f52aSArthur O'Dwyer assert(std::ranges::cbegin(b) == b);
1036842f52aSArthur O'Dwyer
1046842f52aSArthur O'Dwyer BeginMember c[2];
1056842f52aSArthur O'Dwyer assert(std::ranges::begin(c) == c);
1066842f52aSArthur O'Dwyer assert(std::ranges::cbegin(c) == c);
1076842f52aSArthur O'Dwyer
1086842f52aSArthur O'Dwyer return true;
1096842f52aSArthur O'Dwyer }
1106842f52aSArthur O'Dwyer
1116842f52aSArthur O'Dwyer struct BeginMemberReturnsInt {
1126842f52aSArthur O'Dwyer int begin() const;
1136842f52aSArthur O'Dwyer };
1146842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, BeginMemberReturnsInt const&>);
1156842f52aSArthur O'Dwyer
1166842f52aSArthur O'Dwyer struct BeginMemberReturnsVoidPtr {
1176842f52aSArthur O'Dwyer const void *begin() const;
1186842f52aSArthur O'Dwyer };
1196842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, BeginMemberReturnsVoidPtr const&>);
1206842f52aSArthur O'Dwyer
1216842f52aSArthur O'Dwyer struct EmptyBeginMember {
1226842f52aSArthur O'Dwyer struct iterator {};
1236842f52aSArthur O'Dwyer iterator begin() const;
1246842f52aSArthur O'Dwyer };
1256842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, EmptyBeginMember const&>);
1266842f52aSArthur O'Dwyer
1276842f52aSArthur O'Dwyer struct PtrConvertibleBeginMember {
1286842f52aSArthur O'Dwyer struct iterator { operator int*() const; };
1296842f52aSArthur O'Dwyer iterator begin() const;
1306842f52aSArthur O'Dwyer };
1316842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, PtrConvertibleBeginMember const&>);
1326842f52aSArthur O'Dwyer
1336842f52aSArthur O'Dwyer struct NonConstBeginMember {
1346842f52aSArthur O'Dwyer int x;
beginNonConstBeginMember1356842f52aSArthur O'Dwyer constexpr int *begin() { return &x; }
1366842f52aSArthur O'Dwyer };
1376842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeBeginT, NonConstBeginMember &>);
1386842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, NonConstBeginMember const&>);
1396842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember &>);
1406842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember const&>);
1416842f52aSArthur O'Dwyer
1426842f52aSArthur O'Dwyer struct EnabledBorrowingBeginMember {
beginEnabledBorrowingBeginMember1436842f52aSArthur O'Dwyer constexpr int *begin() const { return &globalBuff[0]; }
1446842f52aSArthur O'Dwyer };
1456842f52aSArthur O'Dwyer template<>
1466842f52aSArthur O'Dwyer inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingBeginMember> = true;
1476842f52aSArthur O'Dwyer
148e1e17a64SKonstantin Varlamov struct BeginMemberFunction {
149e1e17a64SKonstantin Varlamov int x;
beginBeginMemberFunction150e1e17a64SKonstantin Varlamov constexpr const int *begin() const { return &x; }
151e1e17a64SKonstantin Varlamov friend int *begin(BeginMemberFunction const&);
152e1e17a64SKonstantin Varlamov };
153e1e17a64SKonstantin Varlamov
154e1e17a64SKonstantin Varlamov struct EmptyPtrBeginMember {
155e1e17a64SKonstantin Varlamov struct Empty {};
156e1e17a64SKonstantin Varlamov Empty x;
beginEmptyPtrBeginMember157e1e17a64SKonstantin Varlamov constexpr const Empty *begin() const { return &x; }
158e1e17a64SKonstantin Varlamov };
159e1e17a64SKonstantin Varlamov
testBeginMember()1606842f52aSArthur O'Dwyer constexpr bool testBeginMember() {
1616842f52aSArthur O'Dwyer BeginMember a;
1626842f52aSArthur O'Dwyer assert(std::ranges::begin(a) == &a.x);
1636842f52aSArthur O'Dwyer assert(std::ranges::cbegin(a) == &a.x);
164502e5df0SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, BeginMember&&>);
165502e5df0SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, BeginMember&&>);
1666842f52aSArthur O'Dwyer
1676842f52aSArthur O'Dwyer NonConstBeginMember b;
1686842f52aSArthur O'Dwyer assert(std::ranges::begin(b) == &b.x);
169502e5df0SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, NonConstBeginMember&>);
1706842f52aSArthur O'Dwyer
1716842f52aSArthur O'Dwyer EnabledBorrowingBeginMember c;
172502e5df0SArthur O'Dwyer assert(std::ranges::begin(c) == &globalBuff[0]);
173502e5df0SArthur O'Dwyer assert(std::ranges::cbegin(c) == &globalBuff[0]);
1746842f52aSArthur O'Dwyer assert(std::ranges::begin(std::move(c)) == &globalBuff[0]);
175502e5df0SArthur O'Dwyer assert(std::ranges::cbegin(std::move(c)) == &globalBuff[0]);
1766842f52aSArthur O'Dwyer
1776842f52aSArthur O'Dwyer BeginMemberFunction d;
1786842f52aSArthur O'Dwyer assert(std::ranges::begin(d) == &d.x);
1796842f52aSArthur O'Dwyer assert(std::ranges::cbegin(d) == &d.x);
1806842f52aSArthur O'Dwyer
1816842f52aSArthur O'Dwyer EmptyPtrBeginMember e;
1826842f52aSArthur O'Dwyer assert(std::ranges::begin(e) == &e.x);
1836842f52aSArthur O'Dwyer assert(std::ranges::cbegin(e) == &e.x);
1846842f52aSArthur O'Dwyer
1856842f52aSArthur O'Dwyer return true;
1866842f52aSArthur O'Dwyer }
1876842f52aSArthur O'Dwyer
1886842f52aSArthur O'Dwyer
1896842f52aSArthur O'Dwyer struct BeginFunction {
1906842f52aSArthur O'Dwyer int x;
begin(BeginFunction const & bf)1916842f52aSArthur O'Dwyer friend constexpr const int *begin(BeginFunction const& bf) { return &bf.x; }
1926842f52aSArthur O'Dwyer };
1936842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeBeginT, BeginFunction const&>);
1946842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &&>);
195*12978b3eSJakub Mazurkiewicz static_assert(std::is_invocable_v<RangeBeginT, BeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
1966842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction const&>);
1976842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction &>);
1986842f52aSArthur O'Dwyer
199e1e17a64SKonstantin Varlamov struct BeginFunctionReturnsInt {
200e1e17a64SKonstantin Varlamov friend int begin(BeginFunctionReturnsInt const&);
2016842f52aSArthur O'Dwyer };
202e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsInt const&>);
2036842f52aSArthur O'Dwyer
204e1e17a64SKonstantin Varlamov struct BeginFunctionReturnsVoidPtr {
205e1e17a64SKonstantin Varlamov friend void *begin(BeginFunctionReturnsVoidPtr const&);
2066842f52aSArthur O'Dwyer };
207e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsVoidPtr const&>);
2086842f52aSArthur O'Dwyer
209e1e17a64SKonstantin Varlamov struct BeginFunctionReturnsPtrConvertible {
210e1e17a64SKonstantin Varlamov struct iterator { operator int*() const; };
211e1e17a64SKonstantin Varlamov friend iterator begin(BeginFunctionReturnsPtrConvertible const&);
2126842f52aSArthur O'Dwyer };
213e1e17a64SKonstantin Varlamov static_assert(!std::is_invocable_v<RangeBeginT, BeginFunctionReturnsPtrConvertible const&>);
2146842f52aSArthur O'Dwyer
2156842f52aSArthur O'Dwyer struct BeginFunctionByValue {
begin(BeginFunctionByValue)2166842f52aSArthur O'Dwyer friend constexpr int *begin(BeginFunctionByValue) { return &globalBuff[1]; }
2176842f52aSArthur O'Dwyer };
2186842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, BeginFunctionByValue>);
2196842f52aSArthur O'Dwyer
2206842f52aSArthur O'Dwyer struct BeginFunctionEnabledBorrowing {
begin(BeginFunctionEnabledBorrowing)2216842f52aSArthur O'Dwyer friend constexpr int *begin(BeginFunctionEnabledBorrowing) { return &globalBuff[2]; }
2226842f52aSArthur O'Dwyer };
2236842f52aSArthur O'Dwyer template<>
2246842f52aSArthur O'Dwyer inline constexpr bool std::ranges::enable_borrowed_range<BeginFunctionEnabledBorrowing> = true;
2256842f52aSArthur O'Dwyer
226e1e17a64SKonstantin Varlamov struct BeginFunctionReturnsEmptyPtr {
2276842f52aSArthur O'Dwyer struct Empty {};
228e1e17a64SKonstantin Varlamov Empty x;
begin(BeginFunctionReturnsEmptyPtr const & bf)229e1e17a64SKonstantin Varlamov friend constexpr const Empty *begin(BeginFunctionReturnsEmptyPtr const& bf) { return &bf.x; }
2306842f52aSArthur O'Dwyer };
2316842f52aSArthur O'Dwyer
232e1e17a64SKonstantin Varlamov struct BeginFunctionWithDataMember {
233e1e17a64SKonstantin Varlamov int x;
234e1e17a64SKonstantin Varlamov int begin;
begin(BeginFunctionWithDataMember const & bf)235e1e17a64SKonstantin Varlamov friend constexpr const int *begin(BeginFunctionWithDataMember const& bf) { return &bf.x; }
2366842f52aSArthur O'Dwyer };
237e1e17a64SKonstantin Varlamov
238e1e17a64SKonstantin Varlamov struct BeginFunctionWithPrivateBeginMember {
239e1e17a64SKonstantin Varlamov int y;
begin(BeginFunctionWithPrivateBeginMember const & bf)240e1e17a64SKonstantin Varlamov friend constexpr const int *begin(BeginFunctionWithPrivateBeginMember const& bf) { return &bf.y; }
241e1e17a64SKonstantin Varlamov private:
242e1e17a64SKonstantin Varlamov const int *begin() const;
243e1e17a64SKonstantin Varlamov };
2446842f52aSArthur O'Dwyer
testBeginFunction()2456842f52aSArthur O'Dwyer constexpr bool testBeginFunction() {
2466842f52aSArthur O'Dwyer BeginFunction a{};
2476842f52aSArthur O'Dwyer const BeginFunction aa{};
248*12978b3eSJakub Mazurkiewicz assert(std::ranges::begin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
2496842f52aSArthur O'Dwyer assert(std::ranges::cbegin(a) == &a.x);
250502e5df0SArthur O'Dwyer assert(std::ranges::begin(aa) == &aa.x);
2516842f52aSArthur O'Dwyer assert(std::ranges::cbegin(aa) == &aa.x);
2526842f52aSArthur O'Dwyer
2536842f52aSArthur O'Dwyer BeginFunctionByValue b{};
2546842f52aSArthur O'Dwyer const BeginFunctionByValue bb{};
2556842f52aSArthur O'Dwyer assert(std::ranges::begin(b) == &globalBuff[1]);
2566842f52aSArthur O'Dwyer assert(std::ranges::cbegin(b) == &globalBuff[1]);
257502e5df0SArthur O'Dwyer assert(std::ranges::begin(bb) == &globalBuff[1]);
2586842f52aSArthur O'Dwyer assert(std::ranges::cbegin(bb) == &globalBuff[1]);
2596842f52aSArthur O'Dwyer
2606842f52aSArthur O'Dwyer BeginFunctionEnabledBorrowing c{};
2616842f52aSArthur O'Dwyer const BeginFunctionEnabledBorrowing cc{};
2626842f52aSArthur O'Dwyer assert(std::ranges::begin(std::move(c)) == &globalBuff[2]);
263502e5df0SArthur O'Dwyer assert(std::ranges::cbegin(std::move(c)) == &globalBuff[2]);
2646842f52aSArthur O'Dwyer assert(std::ranges::begin(std::move(cc)) == &globalBuff[2]);
2656842f52aSArthur O'Dwyer assert(std::ranges::cbegin(std::move(cc)) == &globalBuff[2]);
2666842f52aSArthur O'Dwyer
2676842f52aSArthur O'Dwyer BeginFunctionReturnsEmptyPtr d{};
2686842f52aSArthur O'Dwyer const BeginFunctionReturnsEmptyPtr dd{};
269*12978b3eSJakub Mazurkiewicz assert(std::ranges::begin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
2706842f52aSArthur O'Dwyer assert(std::ranges::cbegin(d) == &d.x);
271502e5df0SArthur O'Dwyer assert(std::ranges::begin(dd) == &dd.x);
2726842f52aSArthur O'Dwyer assert(std::ranges::cbegin(dd) == &dd.x);
2736842f52aSArthur O'Dwyer
2746842f52aSArthur O'Dwyer BeginFunctionWithDataMember e{};
2756842f52aSArthur O'Dwyer const BeginFunctionWithDataMember ee{};
276*12978b3eSJakub Mazurkiewicz assert(std::ranges::begin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
2776842f52aSArthur O'Dwyer assert(std::ranges::begin(ee) == &ee.x);
2786842f52aSArthur O'Dwyer assert(std::ranges::cbegin(e) == &e.x);
2796842f52aSArthur O'Dwyer assert(std::ranges::cbegin(ee) == &ee.x);
2806842f52aSArthur O'Dwyer
2816842f52aSArthur O'Dwyer BeginFunctionWithPrivateBeginMember f{};
2826842f52aSArthur O'Dwyer const BeginFunctionWithPrivateBeginMember ff{};
283*12978b3eSJakub Mazurkiewicz assert(std::ranges::begin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
2846842f52aSArthur O'Dwyer assert(std::ranges::cbegin(f) == &f.y);
285502e5df0SArthur O'Dwyer assert(std::ranges::begin(ff) == &ff.y);
2866842f52aSArthur O'Dwyer assert(std::ranges::cbegin(ff) == &ff.y);
2876842f52aSArthur O'Dwyer
2886842f52aSArthur O'Dwyer return true;
2896842f52aSArthur O'Dwyer }
2906842f52aSArthur O'Dwyer
2916842f52aSArthur O'Dwyer
2926842f52aSArthur O'Dwyer ASSERT_NOEXCEPT(std::ranges::begin(std::declval<int (&)[10]>()));
2936842f52aSArthur O'Dwyer ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval<int (&)[10]>()));
2946842f52aSArthur O'Dwyer
2956842f52aSArthur O'Dwyer struct NoThrowMemberBegin {
2966842f52aSArthur O'Dwyer ThrowingIterator<int> begin() const noexcept; // auto(t.begin()) doesn't throw
2976842f52aSArthur O'Dwyer } ntmb;
2986842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::begin(ntmb)));
2996842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::cbegin(ntmb)));
3006842f52aSArthur O'Dwyer
3016842f52aSArthur O'Dwyer struct NoThrowADLBegin {
3026842f52aSArthur O'Dwyer friend ThrowingIterator<int> begin(NoThrowADLBegin&) noexcept; // auto(begin(t)) doesn't throw
3036842f52aSArthur O'Dwyer friend ThrowingIterator<int> begin(const NoThrowADLBegin&) noexcept;
3046842f52aSArthur O'Dwyer } ntab;
3056842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::begin(ntab)));
3066842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::cbegin(ntab)));
3076842f52aSArthur O'Dwyer
3086842f52aSArthur O'Dwyer struct NoThrowMemberBeginReturnsRef {
3096842f52aSArthur O'Dwyer ThrowingIterator<int>& begin() const noexcept; // auto(t.begin()) may throw
3106842f52aSArthur O'Dwyer } ntmbrr;
3116842f52aSArthur O'Dwyer static_assert(!noexcept(std::ranges::begin(ntmbrr)));
3126842f52aSArthur O'Dwyer static_assert(!noexcept(std::ranges::cbegin(ntmbrr)));
3136842f52aSArthur O'Dwyer
3146842f52aSArthur O'Dwyer struct BeginReturnsArrayRef {
3156842f52aSArthur O'Dwyer auto begin() const noexcept -> int(&)[10];
3166842f52aSArthur O'Dwyer } brar;
3176842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::begin(brar)));
3186842f52aSArthur O'Dwyer static_assert(noexcept(std::ranges::cbegin(brar)));
3196842f52aSArthur O'Dwyer
32085073836SArthur O'Dwyer // Test ADL-proofing.
32185073836SArthur O'Dwyer struct Incomplete;
32285073836SArthur O'Dwyer template<class T> struct Holder { T t; };
32385073836SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, Holder<Incomplete>*>);
3249be193bcSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeBeginT, Holder<Incomplete>*&>);
32585073836SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*>);
3269be193bcSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*&>);
32785073836SArthur O'Dwyer
main(int,char **)3286842f52aSArthur O'Dwyer int main(int, char**) {
329502e5df0SArthur O'Dwyer static_assert(testReturnTypes());
330502e5df0SArthur O'Dwyer
3316842f52aSArthur O'Dwyer testArray();
3326842f52aSArthur O'Dwyer static_assert(testArray());
3336842f52aSArthur O'Dwyer
3346842f52aSArthur O'Dwyer testBeginMember();
3356842f52aSArthur O'Dwyer static_assert(testBeginMember());
3366842f52aSArthur O'Dwyer
3376842f52aSArthur O'Dwyer testBeginFunction();
3386842f52aSArthur O'Dwyer static_assert(testBeginFunction());
3396842f52aSArthur O'Dwyer
3406842f52aSArthur O'Dwyer return 0;
3416842f52aSArthur O'Dwyer }
342