Skip to content

Commit

Permalink
Implement LWG-3778 vector<bool> missing exception specifications (#…
Browse files Browse the repository at this point in the history
…3332)

Co-authored-by: Casey Carter <[email protected]>
  • Loading branch information
frederick-vs-ja and CaseyCarter authored Jan 12, 2023
1 parent dc14f49 commit ed9a3a0
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 14 deletions.
22 changes: 9 additions & 13 deletions stl/inc/vector
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ private:
// insert range [_First, _Last) at end

// For one-at-back, provide strong guarantee.
// Otherwise, provide basic guarantee (despite N4659 26.3.11.5 [vector.modifiers]/1).
// Otherwise, provide basic guarantee (despite N4928 [vector.modifiers]/2).
// Performance note: except for one-at-back, _Emplace_one_at_back()'s strong guarantee is unnecessary here.

for (; _First != _Last; ++_First) {
Expand Down Expand Up @@ -1764,7 +1764,7 @@ public:
if (_Myfirst == _Mylast) { // already empty, nothing to do
// This is an optimization for debug mode: we can avoid taking the debug lock to invalidate iterators.
// Note that when clearing an empty vector, this will preserve past-the-end iterators, which is allowed by
// N4901 [tab:container.seq.req] "a.clear() [...] may invalidate the past-the-end iterator".
// N4928 [sequence.reqmts]/54 "a.clear() [...] may invalidate the past-the-end iterator".
return;
}

Expand Down Expand Up @@ -2776,8 +2776,7 @@ public:
this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal()));
}

_CONSTEXPR20 _Vb_val(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Vectype, _Alvbase>)
: _Myvec(static_cast<_Alvbase>(_Al)), _Mysize(0) {
_CONSTEXPR20 _Vb_val(const _Alloc& _Al) noexcept : _Myvec(static_cast<_Alvbase>(_Al)), _Mysize(0) {
this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal()));
}

Expand Down Expand Up @@ -2876,12 +2875,9 @@ public:
static const int _VBITS = _STD _VBITS;
enum { _EEN_VBITS = _VBITS }; // helper for expression evaluator

_CONSTEXPR20 vector() noexcept(is_nothrow_default_constructible_v<_Mybase>) // strengthened
: _Mybase() {}
_CONSTEXPR20 vector() noexcept(is_nothrow_default_constructible_v<_Alloc>) : _Mybase(_Alloc()) {}

_CONSTEXPR20 explicit vector(const _Alloc& _Al) noexcept(
is_nothrow_constructible_v<_Mybase, const _Alloc&>) // strengthened
: _Mybase(_Al) {}
_CONSTEXPR20 explicit vector(const _Alloc& _Al) noexcept : _Mybase(_Al) {}

_CONSTEXPR20 explicit vector(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc())
: _Mybase(_Count, false, _Al) {
Expand Down Expand Up @@ -2915,13 +2911,12 @@ public:
}
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)

_CONSTEXPR20 vector(vector&& _Right) noexcept(is_nothrow_move_constructible_v<_Mybase>) // strengthened
: _Mybase(_STD move(_Right)) {
_CONSTEXPR20 vector(vector&& _Right) noexcept : _Mybase(_STD move(_Right)) {
this->_Swap_proxy_and_iterators(_Right);
}

_CONSTEXPR20 vector(vector&& _Right, const _Identity_t<_Alloc>& _Al) noexcept(
is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>)
is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>) // strengthened
: _Mybase(_STD move(_Right), _Al) {
if constexpr (!_Alvbase_traits::is_always_equal::value) {
if (this->_Getal() != _Right._Getal()) {
Expand All @@ -2932,7 +2927,8 @@ public:
this->_Swap_proxy_and_iterators(_Right);
}

_CONSTEXPR20 vector& operator=(vector&& _Right) noexcept(is_nothrow_move_assignable_v<_Mybase>) {
_CONSTEXPR20 vector& operator=(vector&& _Right) noexcept(
_Choose_pocma_v<_Alvbase> != _Pocma_values::_No_propagate_allocators) {
if (this == _STD addressof(_Right)) {
return *this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3006,6 +3006,33 @@ DEFINE_TEST_SPECIALIZATION(
//
//

// Adhoc tests for exception specifications of std::vector<bool, Alloc> (LWG-3778)
template <class Alloc>
void assert_vector_bool_noexcept_impl() {
using vec_bool = std::vector<bool, Alloc>;

constexpr bool nothrow_on_pocma = std::allocator_traits<Alloc>::propagate_on_container_move_assignment::value
|| std::allocator_traits<Alloc>::is_always_equal::value;

STATIC_ASSERT(std::is_nothrow_default_constructible_v<vec_bool> == std::is_nothrow_default_constructible_v<Alloc>);
STATIC_ASSERT(std::is_nothrow_constructible_v<vec_bool, const Alloc&>);
STATIC_ASSERT(std::is_nothrow_move_constructible_v<vec_bool>);
STATIC_ASSERT(std::is_nothrow_move_assignable_v<vec_bool> == nothrow_on_pocma);
STATIC_ASSERT(std::is_nothrow_destructible_v<vec_bool>);

STATIC_ASSERT(noexcept(std::declval<vec_bool&>().swap(std::declval<vec_bool&>()))); // strengthened
STATIC_ASSERT(noexcept(std::swap(std::declval<vec_bool&>(), std::declval<vec_bool&>()))); // strengthened
#if _HAS_CXX17
STATIC_ASSERT(std::is_nothrow_swappable_v<vec_bool>); // strengthened
#endif // _HAS_CXX17
}

void assert_vector_bool_noexcept() {
assert_vector_bool_noexcept_impl<std::allocator<bool>>();
assert_vector_bool_noexcept_impl<pocma_allocator<bool>>();
assert_vector_bool_noexcept_impl<non_pocma_allocator<bool>>();
}

template <container_tag Tag>
void assert_container() {
check_all_container_requirements<Tag>();
Expand Down
2 changes: 1 addition & 1 deletion tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ constexpr bool test_interface() {
vec default_constructed;
const auto alloc = default_constructed.get_allocator();
static_assert(is_same_v<remove_const_t<decltype(alloc)>, soccc_allocator<bool>>);
assert(alloc.id == 1);
assert(alloc.id == 2);
assert(alloc.soccc_generation == 0);
}

Expand Down

0 comments on commit ed9a3a0

Please sign in to comment.