diff --git a/stl/inc/bitset b/stl/inc/bitset index 06d1da21bfc..9177af858a5 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -91,7 +91,7 @@ public: friend bitset; public: - _CONSTEXPR23 reference(const reference&) = default; + _CONSTEXPR23 reference(const reference&) noexcept = default; _CONSTEXPR23 ~reference() noexcept {} // TRANSITION, ABI @@ -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); } @@ -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) {} diff --git a/stl/inc/vector b/stl/inc/vector index e3c67338eba..81559f53ac7 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -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()) {} @@ -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 { @@ -2492,7 +2491,6 @@ public: return *this; } -#endif // _HAS_CXX23 _CONSTEXPR20 void flip() noexcept { *const_cast<_Vbase*>(_Getptr()) ^= _Mask(); @@ -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; @@ -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; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 395f8ecd278..fc71f81432b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -85,6 +85,8 @@ // P3323R1 Forbid atomic, Specify atomic_ref // (for atomic) // 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 Stuff @@ -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::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 diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 971a27c8889..c519a64c2db 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -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 diff --git a/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp b/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp index 4e3b174f6fe..f05ab99301f 100644 --- a/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp +++ b/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp @@ -1,8 +1,14 @@ // 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 +#include #include +#include +#include #include using namespace std; @@ -10,7 +16,7 @@ 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() { vector x(100, false); vector y(100, true); @@ -27,3 +33,64 @@ int main() { assert(!y[34]); assert(all_of(y.begin() + 35, y.end(), is_true)); } + +template +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]); + + 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; + vector vb(N); + bitset bs(0); + + check_P3612(vb); + check_P3612(bs); + + static_assert(is_nothrow_copy_constructible_v::reference>, ""); + static_assert(is_nothrow_copy_constructible_v::reference>, ""); +} diff --git a/tests/tr1/tests/vector/test.cpp b/tests/tr1/tests/vector/test.cpp index 3ed42a456d5..97ec389feb6 100644 --- a/tests/tr1/tests/vector/test.cpp +++ b/tests/tr1/tests/vector/test.cpp @@ -4,6 +4,9 @@ // test #define TEST_NAME "" +// Since P3612R1 the static vector::swap(reference, reference) is deprecated +#define _SILENCE_VECTOR_BOOL_STATIC_REFERENCE_SWAP_DEPRECATION_WARNING + #include "tdefs.h" #include #include