Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ec80052
Add tests for new vector<bool> and bitset reference swaps and assignm…
vmichal Nov 12, 2025
4bed2e4
Add swap to bitset::reference, add operator=(bool) const.
vmichal Nov 12, 2025
8c0a262
Add swap to vector<bool>::reference, make operator=(bool) const avail…
vmichal Nov 12, 2025
3ab0600
Mark libcxx test std/containers/sequences/vector.bool/reference.swap.…
vmichal Nov 12, 2025
8f21bc7
Mention the implemented paper P3612R1 in yvals_core.h
vmichal Nov 12, 2025
5c9abf0
Silence deprecation warning in tr1 vector test.
vmichal Nov 12, 2025
d81ed91
Remove meaningless argument name from defaulted copy ctor.
vmichal Nov 13, 2025
2418738
Deprecate std::vector<bool>::swap(reference, reference) only in C++26…
vmichal Nov 19, 2025
a2141cc
Merge branch 'main' into P3612R1
StephanTLavavej Mar 2, 2026
073da9c
List the feature as implemented unconditionally, except for its depre…
StephanTLavavej Mar 2, 2026
14f79a1
Adjust newlines.
StephanTLavavej Mar 2, 2026
ca82ae6
Drop unnecessary `std::`.
StephanTLavavej Mar 2, 2026
8cea3fa
Avoid shadowing `vector` and `bitset`.
StephanTLavavej Mar 2, 2026
3be17ab
`has_noexcept_copy_ctor` provides no value beyond `is_nothrow_copy_co…
StephanTLavavej Mar 2, 2026
1d26326
`typename` => `class`
StephanTLavavej Mar 2, 2026
baf1e0e
West const.
StephanTLavavej Mar 2, 2026
d22a79a
Include `<cstddef>` for `size_t`.
StephanTLavavej Mar 2, 2026
de7ecf9
Avoid `decltype` to improve searchability.
StephanTLavavej Mar 2, 2026
2c46ea3
Extend test coverage, add more assertions.
StephanTLavavej Mar 2, 2026
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
23 changes: 22 additions & 1 deletion stl/inc/bitset
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public:
friend bitset;

public:
_CONSTEXPR23 reference(const reference&) = default;
_CONSTEXPR23 reference(const reference&) noexcept = default;

_CONSTEXPR23 ~reference() noexcept {} // TRANSITION, ABI

Expand All @@ -105,6 +105,11 @@ public:
return *this;
}

_CONSTEXPR23 const reference& operator=(const bool _Val) const noexcept {
_Pbitset->_Set_unchecked(_Mypos, _Val);
return *this;
}

_NODISCARD _CONSTEXPR23 bool operator~() const noexcept {
return !_Pbitset->_Subscript(_Mypos);
}
Expand All @@ -118,6 +123,22 @@ public:
return *this;
}

friend constexpr void swap(reference _Left, reference _Right) noexcept {
bool _Val = _Left; // NOT _STD swap
_Left = _Right;
_Right = _Val;
}

friend constexpr void swap(reference _Left, bool& _Right) noexcept {
bool _Val = _Left; // NOT _STD swap
_Left = _Right;
_Right = _Val;
}

friend constexpr void swap(bool& _Left, reference _Right) noexcept {
swap(_Right, _Left);
}

private:
_CONSTEXPR23 reference(bitset<_Bits>& _Bitset, const size_t _Pos) noexcept : _Pbitset(&_Bitset), _Mypos(_Pos) {}

Expand Down
17 changes: 13 additions & 4 deletions stl/inc/vector
Original file line number Diff line number Diff line change
Expand Up @@ -2463,7 +2463,7 @@ private:
using _Difference_type = typename _Mybase::_Difference_type;

public:
_CONSTEXPR20 _Vb_reference(const _Vb_reference&) = default;
_CONSTEXPR20 _Vb_reference(const _Vb_reference&) noexcept = default;

_CONSTEXPR20 _Vb_reference(const _Mybase& _Right) noexcept
: _Mybase(_Right._Myptr, _Right._Myoff, _Right._Getcont()) {}
Expand All @@ -2482,8 +2482,7 @@ public:
return *this;
}

#if _HAS_CXX23
constexpr const _Vb_reference& operator=(bool _Val) const noexcept {
_CONSTEXPR20 const _Vb_reference& operator=(bool _Val) const noexcept {
if (_Val) {
*const_cast<_Vbase*>(_Getptr()) |= _Mask();
} else {
Expand All @@ -2492,7 +2491,6 @@ public:

return *this;
}
#endif // _HAS_CXX23

_CONSTEXPR20 void flip() noexcept {
*const_cast<_Vbase*>(_Getptr()) ^= _Mask();
Expand All @@ -2519,6 +2517,16 @@ public:
_Right = _Val;
}

friend _CONSTEXPR20 void swap(_Vb_reference _Left, bool& _Right) noexcept {
bool _Val = _Left; // NOT _STD swap
_Left = _Right;
_Right = _Val;
}

friend _CONSTEXPR20 void swap(bool& _Left, _Vb_reference _Right) noexcept {
swap(_Right, _Left);
}

protected:
_CONSTEXPR20 _Vbase _Mask() const noexcept {
return static_cast<_Vbase>(1) << this->_Myoff;
Expand Down Expand Up @@ -3510,6 +3518,7 @@ public:
}
}

_DEPRECATE_VECTOR_BOOL_STATIC_REFERENCE_SWAP
static _CONSTEXPR20 void swap(reference _Left, reference _Right) noexcept {
bool _Val = _Left; // NOT _STD swap
_Left = _Right;
Expand Down
16 changes: 15 additions & 1 deletion stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
// P3323R1 Forbid atomic<cv T>, Specify atomic_ref<cv T>
// (for atomic<cv T>)
// P3503R3 Make Type-Erased Allocator Use In promise And packaged_task Consistent
// P3612R1 Harmonize Proxy-Reference Operations
// (deprecation controlled by _HAS_CXX26)

// _HAS_CXX17 controls:
// N4190 Removing auto_ptr, random_shuffle(), And Old <functional> Stuff
Expand Down Expand Up @@ -1448,7 +1450,19 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect

// STL4048 was "locale::empty() is a non-Standard extension and will be removed in the future."

// next warning number: STL4049

#if _HAS_CXX26 && !defined(_SILENCE_VECTOR_BOOL_STATIC_REFERENCE_SWAP_DEPRECATION_WARNING) \
&& !defined(_SILENCE_ALL_CXX26_DEPRECATION_WARNINGS)
#define _DEPRECATE_VECTOR_BOOL_STATIC_REFERENCE_SWAP \
[[deprecated("warning STL4049: Static std::vector<bool>::swap(reference, reference) is deprecated by C++26 (see " \
"LWG-3638 and P3612R1). Use non-member function swap(reference, reference) instead. You can define " \
"_SILENCE_VECTOR_BOOL_STATIC_REFERENCE_SWAP_DEPRECATION_WARNING or " \
"_SILENCE_ALL_CXX26_DEPRECATION_WARNINGS to suppress this warning.")]]
#else // ^^^ warning enabled / warning disabled vvv
#define _DEPRECATE_VECTOR_BOOL_STATIC_REFERENCE_SWAP
#endif // ^^^ warning disabled ^^^

// next warning number: STL4050

// next error number: STL1014

Expand Down
3 changes: 3 additions & 0 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ std/atomics/atomics.ref/member_types.compile.pass.cpp FAIL
std/thread/futures/futures.promise/uses_allocator.pass.cpp FAIL
std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp FAIL

# libc++ has not implemented P3612R1 "Harmonize Proxy-Reference Operations"
std/containers/sequences/vector.bool/reference.swap.pass.cpp FAIL

# Various bogosity (LLVM-D141004)
std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/ctor_does_not_allocate.pass.cpp FAIL
std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/sync_with_default_resource.pass.cpp FAIL
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// This test was extended with functionality needed for
// P3612R1: Harmonize Proxy-Reference Operations

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cstddef>
#include <type_traits>
#include <vector>

using namespace std;

static const auto is_true = [](bool b) { return b; };
static const auto is_false = [](bool b) { return !b; };

int main() {
void check_values_match() {
Comment thread
StephanTLavavej marked this conversation as resolved.
vector<bool> x(100, false);
vector<bool> y(100, true);

Expand All @@ -27,3 +33,64 @@ int main() {
assert(!y[34]);
assert(all_of(y.begin() + 35, y.end(), is_true));
}

template <class T>
void check_P3612(T& collection) {
auto ref0 = collection[0];
const auto ref1 = collection[1];
auto ref2 = collection[2];

// assignments from bool
ref0 = true;
ref1 = true;
assert(collection[0]);
assert(collection[1]);

ref0 = false;
ref1 = false;
assert(!collection[0]);
assert(!collection[1]);

// assignments from reference
ref2 = true;
ref0 = ref2;
ref1 = ref2;
assert(collection[0]);
assert(collection[1]);

ref2 = false;
ref0 = ref2;
ref1 = ref2;
assert(!collection[0]);
assert(!collection[1]);

collection[0] = true;
collection[1] = false;

swap(collection[0], collection[1]); // swap(reference, reference)
assert(!collection[0]);
assert(collection[1]);

Comment thread
StephanTLavavej marked this conversation as resolved.
bool b = true;
swap(collection[0], b); // swap(reference, bool)
assert(collection[0]);
assert(!b);

swap(b, collection[0]); // swap(bool, reference)
assert(!collection[0]);
assert(b);
}

int main() {
check_values_match();

constexpr size_t N = 10;
Comment thread
StephanTLavavej marked this conversation as resolved.
vector<bool> vb(N);
bitset<N> bs(0);

check_P3612(vb);
check_P3612(bs);

static_assert(is_nothrow_copy_constructible_v<vector<bool>::reference>, "");
static_assert(is_nothrow_copy_constructible_v<bitset<N>::reference>, "");
}
3 changes: 3 additions & 0 deletions tests/tr1/tests/vector/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
// test <vector>
#define TEST_NAME "<vector>"

// Since P3612R1 the static vector<bool>::swap(reference, reference) is deprecated
#define _SILENCE_VECTOR_BOOL_STATIC_REFERENCE_SWAP_DEPRECATION_WARNING

#include "tdefs.h"
#include <stddef.h>
#include <vector>
Expand Down