xref: /llvm-project/libcxx/test/std/iterators/iterator.range/begin-end.container.pass.cpp (revision cb950c9dc9bff37367068310bdfad75c7274915c)
1000940e2SLouis Dionne //===----------------------------------------------------------------------===//
2000940e2SLouis Dionne //
3000940e2SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4000940e2SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
5000940e2SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6000940e2SLouis Dionne //
7000940e2SLouis Dionne //===----------------------------------------------------------------------===//
8000940e2SLouis Dionne 
9000940e2SLouis Dionne // UNSUPPORTED: c++03
10000940e2SLouis Dionne 
11000940e2SLouis Dionne // <iterator>
12000940e2SLouis Dionne //
13000940e2SLouis Dionne // template <class C> constexpr auto begin(C& c) -> decltype(c.begin());                   // constexpr since C++17
14000940e2SLouis Dionne // template <class C> constexpr auto begin(const C& c) -> decltype(c.begin());             // constexpr since C++17
15000940e2SLouis Dionne // template <class C> constexpr auto end(C& c) -> decltype(c.end());                       // constexpr since C++17
16000940e2SLouis Dionne // template <class C> constexpr auto end(const C& c) -> decltype(c.end());                 // constexpr since C++17
17000940e2SLouis Dionne //
18*cb950c9dSLouis Dionne // template <class C> constexpr auto cbegin(const C& c) noexcept(see-below) -> decltype(std::begin(c)); // C++14
19*cb950c9dSLouis Dionne // template <class C> constexpr auto cend(const C& c) noexcept(see-below) -> decltype(std::end(c));     // C++14
20000940e2SLouis Dionne // template <class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin());                 // C++14, constexpr since C++17
21000940e2SLouis Dionne // template <class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin());           // C++14, constexpr since C++17
22000940e2SLouis Dionne // template <class C> constexpr auto rend(C& c) -> decltype(c.rend());                     // C++14, constexpr since C++17
23000940e2SLouis Dionne // template <class C> constexpr auto rend(const C& c) -> decltype(c.rend());               // C++14, constexpr since C++17
24000940e2SLouis Dionne // template <class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c));      // C++14, constexpr since C++17
25000940e2SLouis Dionne // template <class C> constexpr auto crend(const C& c) -> decltype(std::rend(c));          // C++14, constexpr since C++17
26000940e2SLouis Dionne 
27000940e2SLouis Dionne #include <array>
28000940e2SLouis Dionne #include <cassert>
29000940e2SLouis Dionne #include <iterator>
30000940e2SLouis Dionne #include <list>
31000940e2SLouis Dionne #include <vector>
32000940e2SLouis Dionne 
33000940e2SLouis Dionne #include "test_macros.h"
34000940e2SLouis Dionne 
35000940e2SLouis Dionne template <typename C,
36000940e2SLouis Dionne           typename Iterator             = typename C::iterator,
37000940e2SLouis Dionne           typename ConstIterator        = typename C::const_iterator,
38000940e2SLouis Dionne           typename ReverseIterator      = typename C::reverse_iterator,
39000940e2SLouis Dionne           typename ConstReverseIterator = typename C::const_reverse_iterator>
test()40000940e2SLouis Dionne TEST_CONSTEXPR_CXX17 bool test() {
41000940e2SLouis Dionne   C c         = {1, 2, 3};
42000940e2SLouis Dionne   const C& cc = c;
43000940e2SLouis Dionne 
44000940e2SLouis Dionne   // std::begin(C& c) / std::end(C& c)
45000940e2SLouis Dionne   {
46000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::begin(c)), Iterator);
47000940e2SLouis Dionne     assert(std::begin(c) == c.begin());
48000940e2SLouis Dionne 
49000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::end(c)), Iterator);
50000940e2SLouis Dionne     assert(std::end(c) == c.end());
51000940e2SLouis Dionne   }
52000940e2SLouis Dionne 
53000940e2SLouis Dionne   // std::begin(C const& c) / std::end(C const& c)
54000940e2SLouis Dionne   {
55000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::begin(cc)), ConstIterator);
56000940e2SLouis Dionne     assert(std::begin(cc) == cc.begin());
57000940e2SLouis Dionne 
58000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::end(cc)), ConstIterator);
59000940e2SLouis Dionne     assert(std::end(cc) == cc.end());
60000940e2SLouis Dionne   }
61000940e2SLouis Dionne 
62000940e2SLouis Dionne #if TEST_STD_VER >= 14
63000940e2SLouis Dionne   // std::cbegin(C const&) / std::cend(C const&)
64000940e2SLouis Dionne   {
65000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::cbegin(cc)), ConstIterator);
66000940e2SLouis Dionne     static_assert(noexcept(std::cbegin(cc)) == noexcept(std::begin(cc)), "");
67000940e2SLouis Dionne     assert(std::cbegin(cc) == std::begin(cc));
68000940e2SLouis Dionne 
69000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::cend(cc)), ConstIterator);
70000940e2SLouis Dionne     static_assert(noexcept(std::cend(cc)) == noexcept(std::end(cc)), "");
71000940e2SLouis Dionne     assert(std::cend(cc) == std::end(cc));
72000940e2SLouis Dionne 
73000940e2SLouis Dionne     // kind of overkill, but whatever
74000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::cbegin(c)), ConstIterator);
75000940e2SLouis Dionne     static_assert(noexcept(std::cbegin(c)) == noexcept(std::begin(cc)), "");
76000940e2SLouis Dionne     assert(std::cbegin(c) == std::begin(cc));
77000940e2SLouis Dionne 
78000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::cend(c)), ConstIterator);
79000940e2SLouis Dionne     static_assert(noexcept(std::cend(c)) == noexcept(std::end(cc)), "");
80000940e2SLouis Dionne     assert(std::cend(c) == std::end(cc));
81000940e2SLouis Dionne   }
82000940e2SLouis Dionne 
83000940e2SLouis Dionne   // std::rbegin(C& c) / std::rend(C& c)
84000940e2SLouis Dionne   {
85000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::rbegin(c)), ReverseIterator);
86000940e2SLouis Dionne     assert(std::rbegin(c) == c.rbegin());
87000940e2SLouis Dionne 
88000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::rend(c)), ReverseIterator);
89000940e2SLouis Dionne     assert(std::rend(c) == c.rend());
90000940e2SLouis Dionne   }
91000940e2SLouis Dionne 
92000940e2SLouis Dionne   // std::rbegin(C const&) / std::rend(C const&)
93000940e2SLouis Dionne   {
94000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::rbegin(cc)), ConstReverseIterator);
95000940e2SLouis Dionne     assert(std::rbegin(cc) == cc.rbegin());
96000940e2SLouis Dionne 
97000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::rend(cc)), ConstReverseIterator);
98000940e2SLouis Dionne     assert(std::rend(cc) == cc.rend());
99000940e2SLouis Dionne   }
100000940e2SLouis Dionne 
101000940e2SLouis Dionne   // std::crbegin(C const&) / std::crend(C const&)
102000940e2SLouis Dionne   {
103000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::crbegin(cc)), ConstReverseIterator);
104000940e2SLouis Dionne     assert(std::crbegin(cc) == std::rbegin(cc));
105000940e2SLouis Dionne 
106000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::crend(cc)), ConstReverseIterator);
107000940e2SLouis Dionne     assert(std::crend(cc) == std::rend(cc));
108000940e2SLouis Dionne 
109000940e2SLouis Dionne     // kind of overkill, but whatever
110000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::crbegin(c)), ConstReverseIterator);
111000940e2SLouis Dionne     assert(std::crbegin(c) == std::rbegin(cc));
112000940e2SLouis Dionne 
113000940e2SLouis Dionne     ASSERT_SAME_TYPE(decltype(std::crend(c)), ConstReverseIterator);
114000940e2SLouis Dionne     assert(std::crend(c) == std::rend(cc));
115000940e2SLouis Dionne   }
116000940e2SLouis Dionne #endif // TEST_STD_VER >= 14
117000940e2SLouis Dionne 
118000940e2SLouis Dionne   return true;
119000940e2SLouis Dionne }
120000940e2SLouis Dionne 
main(int,char **)121000940e2SLouis Dionne int main(int, char**) {
122000940e2SLouis Dionne   test<std::array<int, 3>>();
123000940e2SLouis Dionne   test<std::list<int>>();
124000940e2SLouis Dionne   test<std::vector<int>>();
125000940e2SLouis Dionne 
126000940e2SLouis Dionne #if TEST_STD_VER >= 17
127000940e2SLouis Dionne   static_assert(test<std::array<int, 3>>());
128000940e2SLouis Dionne #endif
129000940e2SLouis Dionne 
130*cb950c9dSLouis Dionne   // Note: Properly testing the conditional noexcept-ness propagation in std::cbegin and std::cend
131*cb950c9dSLouis Dionne   //       requires using C-style arrays, because those are the only ones with a noexcept std::begin
132*cb950c9dSLouis Dionne   //       and std::end inside namespace std
133*cb950c9dSLouis Dionne #if TEST_STD_VER >= 14
134*cb950c9dSLouis Dionne   {
135*cb950c9dSLouis Dionne     int a[]        = {1, 2, 3};
136*cb950c9dSLouis Dionne     auto const& ca = a;
137*cb950c9dSLouis Dionne     ASSERT_NOEXCEPT(std::cbegin(ca));
138*cb950c9dSLouis Dionne     ASSERT_NOEXCEPT(std::cend(ca));
139*cb950c9dSLouis Dionne 
140*cb950c9dSLouis Dionne     // kind of overkill, but whatever
141*cb950c9dSLouis Dionne     ASSERT_NOEXCEPT(std::cbegin(a));
142*cb950c9dSLouis Dionne     ASSERT_NOEXCEPT(std::cend(a));
143*cb950c9dSLouis Dionne   }
144*cb950c9dSLouis Dionne 
145*cb950c9dSLouis Dionne   // Make sure std::cbegin and std::cend are constexpr in C++14 too (see LWG2280).
146*cb950c9dSLouis Dionne   {
147*cb950c9dSLouis Dionne     static constexpr int a[] = {1, 2, 3};
148*cb950c9dSLouis Dionne     constexpr auto b         = std::cbegin(a);
149*cb950c9dSLouis Dionne     assert(b == a);
150*cb950c9dSLouis Dionne     constexpr auto e = std::cend(a);
151*cb950c9dSLouis Dionne     assert(e == a + 3);
152*cb950c9dSLouis Dionne   }
153*cb950c9dSLouis Dionne #endif
154*cb950c9dSLouis Dionne 
155000940e2SLouis Dionne   return 0;
156000940e2SLouis Dionne }
157