Skip to content

[libc++] Mark vector<bool>::at() as constexpr to conform to C++20 standard #121848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions libcxx/include/__vector/vector_bool.h
Original file line number Diff line number Diff line change
Expand Up @@ -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); }
Expand Down Expand Up @@ -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];
Expand Down
125 changes: 125 additions & 0 deletions libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
121 changes: 121 additions & 0 deletions libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
Loading