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-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03
10
11// <iterator>
12//
13// template <class C> constexpr auto begin(C& c) -> decltype(c.begin()); // constexpr since C++17
14// template <class C> constexpr auto begin(const C& c) -> decltype(c.begin()); // constexpr since C++17
15// template <class C> constexpr auto end(C& c) -> decltype(c.end()); // constexpr since C++17
16// template <class C> constexpr auto end(const C& c) -> decltype(c.end()); // constexpr since C++17
17//
18// template <class C> constexpr auto cbegin(const C& c) noexcept(see-below) -> decltype(std::begin(c)); // C++14
19// template <class C> constexpr auto cend(const C& c) noexcept(see-below) -> decltype(std::end(c)); // C++14
20// template <class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin()); // C++14, constexpr since C++17
21// template <class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin()); // C++14, constexpr since C++17
22// template <class C> constexpr auto rend(C& c) -> decltype(c.rend()); // C++14, constexpr since C++17
23// template <class C> constexpr auto rend(const C& c) -> decltype(c.rend()); // C++14, constexpr since C++17
24// template <class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c)); // C++14, constexpr since C++17
25// template <class C> constexpr auto crend(const C& c) -> decltype(std::rend(c)); // C++14, constexpr since C++17
26
27#include <array>
28#include <cassert>
29#include <iterator>
30#include <list>
31#include <vector>
32
33#include "test_macros.h"
34
35template <typename C,
36 typename Iterator = typename C::iterator,
37 typename ConstIterator = typename C::const_iterator,
38 typename ReverseIterator = typename C::reverse_iterator,
39 typename ConstReverseIterator = typename C::const_reverse_iterator>
40TEST_CONSTEXPR_CXX17 bool test() {
41 C c = {1, 2, 3};
42 const C& cc = c;
43
44 // std::begin(C& c) / std::end(C& c)
45 {
46 ASSERT_SAME_TYPE(decltype(std::begin(c)), Iterator);
47 assert(std::begin(c) == c.begin());
48
49 ASSERT_SAME_TYPE(decltype(std::end(c)), Iterator);
50 assert(std::end(c) == c.end());
51 }
52
53 // std::begin(C const& c) / std::end(C const& c)
54 {
55 ASSERT_SAME_TYPE(decltype(std::begin(cc)), ConstIterator);
56 assert(std::begin(cc) == cc.begin());
57
58 ASSERT_SAME_TYPE(decltype(std::end(cc)), ConstIterator);
59 assert(std::end(cc) == cc.end());
60 }
61
62#if TEST_STD_VER >= 14
63 // std::cbegin(C const&) / std::cend(C const&)
64 {
65 ASSERT_SAME_TYPE(decltype(std::cbegin(cc)), ConstIterator);
66 static_assert(noexcept(std::cbegin(cc)) == noexcept(std::begin(cc)), "");
67 assert(std::cbegin(cc) == std::begin(cc));
68
69 ASSERT_SAME_TYPE(decltype(std::cend(cc)), ConstIterator);
70 static_assert(noexcept(std::cend(cc)) == noexcept(std::end(cc)), "");
71 assert(std::cend(cc) == std::end(cc));
72
73 // kind of overkill, but whatever
74 ASSERT_SAME_TYPE(decltype(std::cbegin(c)), ConstIterator);
75 static_assert(noexcept(std::cbegin(c)) == noexcept(std::begin(cc)), "");
76 assert(std::cbegin(c) == std::begin(cc));
77
78 ASSERT_SAME_TYPE(decltype(std::cend(c)), ConstIterator);
79 static_assert(noexcept(std::cend(c)) == noexcept(std::end(cc)), "");
80 assert(std::cend(c) == std::end(cc));
81 }
82
83 // std::rbegin(C& c) / std::rend(C& c)
84 {
85 ASSERT_SAME_TYPE(decltype(std::rbegin(c)), ReverseIterator);
86 assert(std::rbegin(c) == c.rbegin());
87
88 ASSERT_SAME_TYPE(decltype(std::rend(c)), ReverseIterator);
89 assert(std::rend(c) == c.rend());
90 }
91
92 // std::rbegin(C const&) / std::rend(C const&)
93 {
94 ASSERT_SAME_TYPE(decltype(std::rbegin(cc)), ConstReverseIterator);
95 assert(std::rbegin(cc) == cc.rbegin());
96
97 ASSERT_SAME_TYPE(decltype(std::rend(cc)), ConstReverseIterator);
98 assert(std::rend(cc) == cc.rend());
99 }
100
101 // std::crbegin(C const&) / std::crend(C const&)
102 {
103 ASSERT_SAME_TYPE(decltype(std::crbegin(cc)), ConstReverseIterator);
104 assert(std::crbegin(cc) == std::rbegin(cc));
105
106 ASSERT_SAME_TYPE(decltype(std::crend(cc)), ConstReverseIterator);
107 assert(std::crend(cc) == std::rend(cc));
108
109 // kind of overkill, but whatever
110 ASSERT_SAME_TYPE(decltype(std::crbegin(c)), ConstReverseIterator);
111 assert(std::crbegin(c) == std::rbegin(cc));
112
113 ASSERT_SAME_TYPE(decltype(std::crend(c)), ConstReverseIterator);
114 assert(std::crend(c) == std::rend(cc));
115 }
116#endif // TEST_STD_VER >= 14
117
118 return true;
119}
120
121int main(int, char**) {
122 test<std::array<int, 3>>();
123 test<std::list<int>>();
124 test<std::vector<int>>();
125
126#if TEST_STD_VER >= 17
127 static_assert(test<std::array<int, 3>>());
128#endif
129
130 // Note: Properly testing the conditional noexcept-ness propagation in std::cbegin and std::cend
131 // requires using C-style arrays, because those are the only ones with a noexcept std::begin
132 // and std::end inside namespace std
133#if TEST_STD_VER >= 14
134 {
135 int a[] = {1, 2, 3};
136 auto const& ca = a;
137 ASSERT_NOEXCEPT(std::cbegin(ca));
138 ASSERT_NOEXCEPT(std::cend(ca));
139
140 // kind of overkill, but whatever
141 ASSERT_NOEXCEPT(std::cbegin(a));
142 ASSERT_NOEXCEPT(std::cend(a));
143 }
144
145 // Make sure std::cbegin and std::cend are constexpr in C++14 too (see LWG2280).
146 {
147 static constexpr int a[] = {1, 2, 3};
148 constexpr auto b = std::cbegin(a);
149 assert(b == a);
150 constexpr auto e = std::cend(a);
151 assert(e == a + 3);
152 }
153#endif
154
155 return 0;
156}
157

source code of libcxx/test/std/iterators/iterator.range/begin-end.container.pass.cpp