diff --git a/stl/inc/bitset b/stl/inc/bitset index 13ed3252884..e928bc86065 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -85,7 +85,7 @@ public: friend bitset; public: - _CONSTEXPR23 reference(const reference&) = default; + _CONSTEXPR23 reference(const reference&) noexcept = default; _CONSTEXPR23 ~reference() noexcept {} // TRANSITION, ABI @@ -99,6 +99,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); } @@ -112,6 +117,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 dafac7c5933..df0b06a4579 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -2461,7 +2461,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()) {} @@ -2480,8 +2480,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 { @@ -2490,7 +2489,6 @@ public: return *this; } -#endif // _HAS_CXX23 _CONSTEXPR20 void flip() noexcept { *const_cast<_Vbase*>(_Getptr()) ^= _Mask(); @@ -2517,6 +2515,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; @@ -3509,6 +3517,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 0ccf71729ed..073fb1362fb 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -415,6 +415,10 @@ // P2614R2 Deprecating float_denorm_style, numeric_limits::has_denorm, numeric_limits::has_denorm_loss // Other C++23 deprecation warnings +// _HAS_CXX26 and _SILENCE_ALL_CXX26_DEPRECATION_WARNINGS control: +// P3612R1 Harmonize Proxy-Reference Operations +// Other C++26 deprecation warnings + // Parallel Algorithms Notes // C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. // This implementation parallelizes several common algorithm calls, but not all. @@ -1512,7 +1516,19 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define _DEPRECATE_LOCALE_EMPTY #endif // ^^^ warning disabled ^^^ -// 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: STL1013 diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 343abccc27a..1181d6470b8 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -149,6 +149,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..2e696aff889 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,13 @@ // 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 using namespace std; @@ -10,7 +15,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 +32,50 @@ 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]; + auto const ref1 = collection[1]; + + // assignments from bool + ref0 = true; + ref1 = false; + // assignments from reference + ref0 = ref1; + ref1 = ref0; + + collection[0] = true; + collection[1] = false; + + swap(collection[0], collection[1]); // swap(reference, reference) + assert(!collection[0]); + + bool b = true; + swap(collection[0], b); // swap(reference, bool) + assert(collection[0]); + + swap(b, collection[0]); // swap(bool, reference) + assert(!collection[0]); +} + +template +constexpr bool has_noexcept_copy_ctor = noexcept(T(std::declval())); + +int main() { + check_values_match(); + + + constexpr size_t N = 10; + vector vector(N); + bitset bitset(0); + + check_P3612(vector); + check_P3612(bitset); + + static_assert(std::is_nothrow_copy_constructible_v, ""); + static_assert(std::is_nothrow_copy_constructible_v, ""); + static_assert(has_noexcept_copy_ctor, ""); + static_assert(has_noexcept_copy_ctor, ""); +} 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