diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 8658745b8a8f9..4c334176a037e 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -279,8 +279,8 @@ class _LIBCPP_TEMPLATE_VIS vector { _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::shrink_to_fit() _NO } template -typename vector::reference vector::at(size_type __n) { +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::reference vector::at(size_type __n) { if (__n >= size()) this->__throw_out_of_range(); return (*this)[__n]; } template -typename vector::const_reference vector::at(size_type __n) const { +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::const_reference +vector::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.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp new file mode 100644 index 0000000000000..16832dd831e61 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// reference at(size_type n); // constexpr since C++20 + +#include +#include +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +#ifndef TEST_HAS_NO_EXCEPTIONS +# include +#endif + +template +TEST_CONSTEXPR_CXX20 void test() { + using C = std::vector; + 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 +void test_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + { + bool a[] = {1, 0, 1, 1}; + using C = std::vector; + 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(-1)); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + std::vector 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 >(); + test >(); + test >(); + return true; +} + +void test_exceptions() { + test_exception >(); + test_exception >(); + test_exception >(); +} + +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 0000000000000..5ed794d13f193 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// const_reference at(size_type n) const; // constexpr since C++20 + +#include +#include +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +#ifndef TEST_HAS_NO_EXCEPTIONS +# include +#endif + +template +TEST_CONSTEXPR_CXX20 void test() { + using C = const std::vector; + 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 +void test_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + { + bool a[] = {1, 0, 1, 1}; + using C = const std::vector; + 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(-1)); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + std::vector 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 >(); + test >(); + test >(); + return true; +} + +void test_exceptions() { + test_exception >(); + test_exception >(); + test_exception >(); +} + +int main(int, char**) { + tests(); + test_exceptions(); + +#if TEST_STD_VER >= 20 + static_assert(tests()); +#endif + + return 0; +}