Skip to content

Commit 71e9a48

Browse files
authored
[libc++] Mark vector<bool>::at() as constexpr to conform to C++20 standard (#121848)
Closes #121844.
1 parent 858f025 commit 71e9a48

File tree

3 files changed

+251
-4
lines changed

3 files changed

+251
-4
lines changed

libcxx/include/__vector/vector_bool.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ class _LIBCPP_TEMPLATE_VIS vector<bool, _Allocator> {
279279
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __n) const {
280280
return __make_ref(__n);
281281
}
282-
_LIBCPP_HIDE_FROM_ABI reference at(size_type __n);
283-
_LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const;
282+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n);
283+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const;
284284

285285
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() { return __make_ref(0); }
286286
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const { return __make_ref(0); }
@@ -853,14 +853,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::shrink_to_fit() _NO
853853
}
854854

855855
template <class _Allocator>
856-
typename vector<bool, _Allocator>::reference vector<bool, _Allocator>::at(size_type __n) {
856+
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::reference vector<bool, _Allocator>::at(size_type __n) {
857857
if (__n >= size())
858858
this->__throw_out_of_range();
859859
return (*this)[__n];
860860
}
861861

862862
template <class _Allocator>
863-
typename vector<bool, _Allocator>::const_reference vector<bool, _Allocator>::at(size_type __n) const {
863+
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::const_reference
864+
vector<bool, _Allocator>::at(size_type __n) const {
864865
if (__n >= size())
865866
this->__throw_out_of_range();
866867
return (*this)[__n];
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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+
// <vector>
10+
11+
// reference at(size_type n); // constexpr since C++20
12+
13+
#include <cassert>
14+
#include <memory>
15+
#include <vector>
16+
17+
#include "min_allocator.h"
18+
#include "test_allocator.h"
19+
#include "test_macros.h"
20+
21+
#ifndef TEST_HAS_NO_EXCEPTIONS
22+
# include <stdexcept>
23+
#endif
24+
25+
template <typename Allocator>
26+
TEST_CONSTEXPR_CXX20 void test() {
27+
using C = std::vector<bool, Allocator>;
28+
using reference = typename C::reference;
29+
bool a[] = {1, 0, 1, 0, 1};
30+
C v(a, a + sizeof(a) / sizeof(a[0]));
31+
ASSERT_SAME_TYPE(reference, decltype(v.at(0)));
32+
assert(v.at(0) == true);
33+
assert(v.at(1) == false);
34+
assert(v.at(2) == true);
35+
assert(v.at(3) == false);
36+
assert(v.at(4) == true);
37+
v.at(1) = 1;
38+
assert(v.at(1) == true);
39+
v.at(3) = 1;
40+
assert(v.at(3) == true);
41+
}
42+
43+
template <typename Allocator>
44+
void test_exception() {
45+
#ifndef TEST_HAS_NO_EXCEPTIONS
46+
{
47+
bool a[] = {1, 0, 1, 1};
48+
using C = std::vector<bool, Allocator>;
49+
C v(a, a + sizeof(a) / sizeof(a[0]));
50+
51+
try {
52+
TEST_IGNORE_NODISCARD v.at(4);
53+
assert(false);
54+
} catch (std::out_of_range const&) {
55+
// pass
56+
} catch (...) {
57+
assert(false);
58+
}
59+
60+
try {
61+
TEST_IGNORE_NODISCARD v.at(5);
62+
assert(false);
63+
} catch (std::out_of_range const&) {
64+
// pass
65+
} catch (...) {
66+
assert(false);
67+
}
68+
69+
try {
70+
TEST_IGNORE_NODISCARD v.at(6);
71+
assert(false);
72+
} catch (std::out_of_range const&) {
73+
// pass
74+
} catch (...) {
75+
assert(false);
76+
}
77+
78+
try {
79+
using size_type = typename C::size_type;
80+
TEST_IGNORE_NODISCARD v.at(static_cast<size_type>(-1));
81+
assert(false);
82+
} catch (std::out_of_range const&) {
83+
// pass
84+
} catch (...) {
85+
assert(false);
86+
}
87+
}
88+
89+
{
90+
std::vector<bool, Allocator> v;
91+
try {
92+
TEST_IGNORE_NODISCARD v.at(0);
93+
assert(false);
94+
} catch (std::out_of_range const&) {
95+
// pass
96+
} catch (...) {
97+
assert(false);
98+
}
99+
}
100+
#endif
101+
}
102+
103+
TEST_CONSTEXPR_CXX20 bool tests() {
104+
test<std::allocator<bool> >();
105+
test<min_allocator<bool> >();
106+
test<test_allocator<bool> >();
107+
return true;
108+
}
109+
110+
void test_exceptions() {
111+
test_exception<std::allocator<bool> >();
112+
test_exception<min_allocator<bool> >();
113+
test_exception<test_allocator<bool> >();
114+
}
115+
116+
int main(int, char**) {
117+
tests();
118+
test_exceptions();
119+
120+
#if TEST_STD_VER >= 20
121+
static_assert(tests());
122+
#endif
123+
124+
return 0;
125+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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+
// <vector>
10+
11+
// const_reference at(size_type n) const; // constexpr since C++20
12+
13+
#include <cassert>
14+
#include <memory>
15+
#include <vector>
16+
17+
#include "min_allocator.h"
18+
#include "test_allocator.h"
19+
#include "test_macros.h"
20+
21+
#ifndef TEST_HAS_NO_EXCEPTIONS
22+
# include <stdexcept>
23+
#endif
24+
25+
template <typename Allocator>
26+
TEST_CONSTEXPR_CXX20 void test() {
27+
using C = const std::vector<bool, Allocator>;
28+
using const_reference = typename C::const_reference;
29+
bool a[] = {1, 0, 1, 0, 1};
30+
C v(a, a + sizeof(a) / sizeof(a[0]));
31+
ASSERT_SAME_TYPE(const_reference, decltype(v.at(0)));
32+
assert(v.at(0) == true);
33+
assert(v.at(1) == false);
34+
assert(v.at(2) == true);
35+
assert(v.at(3) == false);
36+
assert(v.at(4) == true);
37+
}
38+
39+
template <typename Allocator>
40+
void test_exception() {
41+
#ifndef TEST_HAS_NO_EXCEPTIONS
42+
{
43+
bool a[] = {1, 0, 1, 1};
44+
using C = const std::vector<bool, Allocator>;
45+
C v(a, a + sizeof(a) / sizeof(a[0]));
46+
47+
try {
48+
TEST_IGNORE_NODISCARD v.at(4);
49+
assert(false);
50+
} catch (std::out_of_range const&) {
51+
// pass
52+
} catch (...) {
53+
assert(false);
54+
}
55+
56+
try {
57+
TEST_IGNORE_NODISCARD v.at(5);
58+
assert(false);
59+
} catch (std::out_of_range const&) {
60+
// pass
61+
} catch (...) {
62+
assert(false);
63+
}
64+
65+
try {
66+
TEST_IGNORE_NODISCARD v.at(6);
67+
assert(false);
68+
} catch (std::out_of_range const&) {
69+
// pass
70+
} catch (...) {
71+
assert(false);
72+
}
73+
74+
try {
75+
using size_type = typename C::size_type;
76+
TEST_IGNORE_NODISCARD v.at(static_cast<size_type>(-1));
77+
assert(false);
78+
} catch (std::out_of_range const&) {
79+
// pass
80+
} catch (...) {
81+
assert(false);
82+
}
83+
}
84+
85+
{
86+
std::vector<bool, Allocator> v;
87+
try {
88+
TEST_IGNORE_NODISCARD v.at(0);
89+
assert(false);
90+
} catch (std::out_of_range const&) {
91+
// pass
92+
} catch (...) {
93+
assert(false);
94+
}
95+
}
96+
#endif
97+
}
98+
99+
TEST_CONSTEXPR_CXX20 bool tests() {
100+
test<std::allocator<bool> >();
101+
test<min_allocator<bool> >();
102+
test<test_allocator<bool> >();
103+
return true;
104+
}
105+
106+
void test_exceptions() {
107+
test_exception<std::allocator<bool> >();
108+
test_exception<min_allocator<bool> >();
109+
test_exception<test_allocator<bool> >();
110+
}
111+
112+
int main(int, char**) {
113+
tests();
114+
test_exceptions();
115+
116+
#if TEST_STD_VER >= 20
117+
static_assert(tests());
118+
#endif
119+
120+
return 0;
121+
}

0 commit comments

Comments
 (0)