[libcxx-commits] [libcxx] [libc++] Mark vector<bool>::at() as constexpr to conform to C++20 standard (PR #121848)
Peng Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jan 6 20:32:52 PST 2025
https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/121848
>From a772b52c9dec6cf165e962d0d1e15aa2c563b04c Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Mon, 6 Jan 2025 16:30:53 -0500
Subject: [PATCH 1/2] Mark vector<bool>::at() as constexpr
---
libcxx/include/__vector/vector_bool.h | 9 ++--
.../vector.bool/at.constexpr.pass.cpp | 42 +++++++++++++++++++
2 files changed, 47 insertions(+), 4 deletions(-)
create mode 100644 libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp
diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h
index 8658745b8a8f9e..4c334176a037e1 100644
--- a/libcxx/include/__vector/vector_bool.h
+++ b/libcxx/include/__vector/vector_bool.h
@@ -279,8 +279,8 @@ class _LIBCPP_TEMPLATE_VIS vector<bool, _Allocator> {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __n) const {
return __make_ref(__n);
}
- _LIBCPP_HIDE_FROM_ABI reference at(size_type __n);
- _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const;
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n);
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() { return __make_ref(0); }
_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
}
template <class _Allocator>
-typename vector<bool, _Allocator>::reference vector<bool, _Allocator>::at(size_type __n) {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::reference vector<bool, _Allocator>::at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
return (*this)[__n];
}
template <class _Allocator>
-typename vector<bool, _Allocator>::const_reference vector<bool, _Allocator>::at(size_type __n) const {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<bool, _Allocator>::const_reference
+vector<bool, _Allocator>::at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
return (*this)[__n];
diff --git a/libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp
new file mode 100644
index 00000000000000..cc9ce99f9488b5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// constexpr const_reference at(size_type n) const;
+// constexpr reference at(size_type n);
+
+#include <cassert>
+#include <memory>
+#include <vector>
+
+#include "min_allocator.h"
+#include "test_allocator.h"
+
+template <typename T, typename Allocator>
+constexpr void test() {
+ std::vector<T, Allocator> v{1, 0, 1};
+ assert(v.at(0) == 1);
+ assert(v.at(1) == 0);
+ assert(v.at(2) == 1);
+}
+
+constexpr bool tests() {
+ test<bool, std::allocator<bool>>();
+ test<bool, min_allocator<bool>>();
+ test<bool, test_allocator<bool>>();
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+
+ return 0;
+}
>From 8d6c5824efa024944870373cfcf54ed837d9e095 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Mon, 6 Jan 2025 23:30:09 -0500
Subject: [PATCH 2/2] Add tests for at() function in all modes
---
.../vector.bool/at.constexpr.pass.cpp | 42 ------
.../sequences/vector.bool/at.pass.cpp | 125 ++++++++++++++++++
.../sequences/vector.bool/at_const.pass.cpp | 121 +++++++++++++++++
3 files changed, 246 insertions(+), 42 deletions(-)
delete mode 100644 libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp
diff --git a/libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp
deleted file mode 100644
index cc9ce99f9488b5..00000000000000
--- a/libcxx/test/std/containers/sequences/vector.bool/at.constexpr.pass.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// constexpr const_reference at(size_type n) const;
-// constexpr reference at(size_type n);
-
-#include <cassert>
-#include <memory>
-#include <vector>
-
-#include "min_allocator.h"
-#include "test_allocator.h"
-
-template <typename T, typename Allocator>
-constexpr void test() {
- std::vector<T, Allocator> v{1, 0, 1};
- assert(v.at(0) == 1);
- assert(v.at(1) == 0);
- assert(v.at(2) == 1);
-}
-
-constexpr bool tests() {
- test<bool, std::allocator<bool>>();
- test<bool, min_allocator<bool>>();
- test<bool, test_allocator<bool>>();
-
- return true;
-}
-
-int main(int, char**) {
- tests();
- static_assert(tests());
-
- return 0;
-}
diff --git a/libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp
new file mode 100644
index 00000000000000..587c573534c01c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp
@@ -0,0 +1,125 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// reference at(size_type n); // constexpr since C++20
+
+#include <cassert>
+#include <memory>
+#include <vector>
+
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+template <typename Allocator>
+TEST_CONSTEXPR_CXX20 void test() {
+ using C = std::vector<bool, Allocator>;
+ using reference = typename C::reference;
+ bool a[] = {1, 0, 1, 0, 1};
+ C v(a, a + sizeof(a) / sizeof(a[0]));
+ ASSERT_SAME_TYPE(reference, decltype(v.at(0)));
+ assert(v.at(0) == true);
+ assert(v.at(1) == false);
+ assert(v.at(2) == true);
+ assert(v.at(3) == false);
+ assert(v.at(4) == true);
+ v.at(1) = 1;
+ assert(v.at(1) == true);
+ v.at(3) = 1;
+ assert(v.at(3) == true);
+}
+
+template <typename Allocator>
+void test_exception() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ bool a[] = {1, 0, 1, 1};
+ using C = std::vector<bool, Allocator>;
+ C v(a, a + sizeof(a) / sizeof(a[0]));
+
+ try {
+ TEST_IGNORE_NODISCARD v.at(4);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+
+ try {
+ TEST_IGNORE_NODISCARD v.at(5);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+
+ try {
+ TEST_IGNORE_NODISCARD v.at(6);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+
+ try {
+ using size_type = typename C::size_type;
+ TEST_IGNORE_NODISCARD v.at(static_cast<size_type>(-1));
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+ }
+
+ {
+ std::vector<bool, Allocator> v;
+ try {
+ TEST_IGNORE_NODISCARD v.at(0);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+ }
+#endif
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ test<std::allocator<bool>>();
+ test<min_allocator<bool>>();
+ test<test_allocator<bool>>();
+ return true;
+}
+
+void test_exceptions() {
+ test_exception<std::allocator<bool>>();
+ test_exception<min_allocator<bool>>();
+ test_exception<test_allocator<bool>>();
+}
+
+int main(int, char**) {
+ tests();
+ test_exceptions();
+
+#if TEST_STD_VER >= 20
+ static_assert(tests());
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp
new file mode 100644
index 00000000000000..6ad3e70b2b5875
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// const_reference at(size_type n) const; // constexpr since C++20
+
+#include <cassert>
+#include <memory>
+#include <vector>
+
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+template <typename Allocator>
+TEST_CONSTEXPR_CXX20 void test() {
+ using C = const std::vector<bool, Allocator>;
+ using const_reference = typename C::const_reference;
+ bool a[] = {1, 0, 1, 0, 1};
+ C v(a, a + sizeof(a) / sizeof(a[0]));
+ ASSERT_SAME_TYPE(const_reference, decltype(v.at(0)));
+ assert(v.at(0) == true);
+ assert(v.at(1) == false);
+ assert(v.at(2) == true);
+ assert(v.at(3) == false);
+ assert(v.at(4) == true);
+}
+
+template <typename Allocator>
+void test_exception() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ bool a[] = {1, 0, 1, 1};
+ using C = const std::vector<bool, Allocator>;
+ C v(a, a + sizeof(a) / sizeof(a[0]));
+
+ try {
+ TEST_IGNORE_NODISCARD v.at(4);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+
+ try {
+ TEST_IGNORE_NODISCARD v.at(5);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+
+ try {
+ TEST_IGNORE_NODISCARD v.at(6);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+
+ try {
+ using size_type = typename C::size_type;
+ TEST_IGNORE_NODISCARD v.at(static_cast<size_type>(-1));
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+ }
+
+ {
+ std::vector<bool, Allocator> v;
+ try {
+ TEST_IGNORE_NODISCARD v.at(0);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+ }
+#endif
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ test<std::allocator<bool>>();
+ test<min_allocator<bool>>();
+ test<test_allocator<bool>>();
+ return true;
+}
+
+void test_exceptions() {
+ test_exception<std::allocator<bool>>();
+ test_exception<min_allocator<bool>>();
+ test_exception<test_allocator<bool>>();
+}
+
+int main(int, char**) {
+ tests();
+ test_exceptions();
+
+#if TEST_STD_VER >= 20
+ static_assert(tests());
+#endif
+
+ return 0;
+}
More information about the libcxx-commits
mailing list