Skip to content
Snippets Groups Projects
Unverified Commit 0d450aa6 authored by Joe Loser's avatar Joe Loser
Browse files

[libc++] P2401: conditional noexcept for std::exchange

Implement P2401 which adds a `noexcept` specification to
`std::exchange`. Treated as a defect fix which is the motivation for
applying this change to all standards mode rather than just C++23 or
later as the paper suggests.

Reviewed By: Quuxplusone, Mordante, #libc

Differential Revision: https://reviews.llvm.org/D111481
parent 63aab406
No related branches found
No related tags found
No related merge requests found
...@@ -36,5 +36,5 @@ ...@@ -36,5 +36,5 @@
"`P2321 <https://wg21.link/P2321>`__","LWG","``zip``","October 2021","","" "`P2321 <https://wg21.link/P2321>`__","LWG","``zip``","October 2021","",""
"`P2340 <https://wg21.link/P2340>`__","LWG","Clarifying the status of the 'C headers'","October 2021","","" "`P2340 <https://wg21.link/P2340>`__","LWG","Clarifying the status of the 'C headers'","October 2021","",""
"`P2393 <https://wg21.link/P2393>`__","LWG","Cleaning up ``integer``-class types","October 2021","","" "`P2393 <https://wg21.link/P2393>`__","LWG","Cleaning up ``integer``-class types","October 2021","",""
"`P2401 <https://wg21.link/P2401>`__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","","" "`P2401 <https://wg21.link/P2401>`__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","|Complete|","14.0"
"","","","","","" "","","","","",""
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <__config> #include <__config>
#include <__utility/forward.h> #include <__utility/forward.h>
#include <__utility/move.h> #include <__utility/move.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header #pragma GCC system_header
...@@ -22,7 +23,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD ...@@ -22,7 +23,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 11 #if _LIBCPP_STD_VER > 11
template<class _T1, class _T2 = _T1> template<class _T1, class _T2 = _T1>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_T1 exchange(_T1& __obj, _T2 && __new_value) _T1 exchange(_T1& __obj, _T2&& __new_value)
noexcept(is_nothrow_move_constructible<_T1>::value && is_nothrow_assignable<_T1&, _T2>::value)
{ {
_T1 __old_value = _VSTD::move(__obj); _T1 __old_value = _VSTD::move(__obj);
__obj = _VSTD::forward<_T2>(__new_value); __obj = _VSTD::forward<_T2>(__new_value);
......
...@@ -183,7 +183,8 @@ template<class... T> ...@@ -183,7 +183,8 @@ template<class... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>; using index_sequence_for = make_index_sequence<sizeof...(T)>;
template<class T, class U=T> template<class T, class U=T>
T exchange(T& obj, U&& new_value); constexpr T exchange(T& obj, U&& new_value)
noexcept(is_nothrow_move_constructible<T>::value && is_nothrow_assignable<T&, U>::value); // constexpr in C++17, noexcept in C++23
// 20.2.7, in-place construction // C++17 // 20.2.7, in-place construction // C++17
struct in_place_t { struct in_place_t {
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
// template<class T, class U=T> // template<class T, class U=T>
// constexpr T // constexpr after C++17 // constexpr T // constexpr after C++17
// exchange(T& obj, U&& new_value); // exchange(T& obj, U&& new_value)
// noexcept(is_nothrow_move_constructible<T>::value && is_nothrow_assignable<T&, U>::value);
#include <utility> #include <utility>
#include <cassert> #include <cassert>
...@@ -37,7 +38,36 @@ TEST_CONSTEXPR bool test_constexpr() { ...@@ -37,7 +38,36 @@ TEST_CONSTEXPR bool test_constexpr() {
} }
#endif #endif
template<bool Move, bool Assign>
struct TestNoexcept {
TestNoexcept() = default;
TestNoexcept(const TestNoexcept&);
TestNoexcept(TestNoexcept&&) noexcept(Move);
TestNoexcept& operator=(const TestNoexcept&);
TestNoexcept& operator=(TestNoexcept&&) noexcept(Assign);
};
constexpr bool test_noexcept() {
{
int x = 42;
ASSERT_NOEXCEPT(std::exchange(x, 42));
}
{
TestNoexcept<true, true> x;
ASSERT_NOEXCEPT(std::exchange(x, std::move(x)));
ASSERT_NOT_NOEXCEPT(std::exchange(x, x)); // copy-assignment is not noexcept
}
{
TestNoexcept<true, false> x;
ASSERT_NOT_NOEXCEPT(std::exchange(x, std::move(x)));
}
{
TestNoexcept<false, true> x;
ASSERT_NOT_NOEXCEPT(std::exchange(x, std::move(x)));
}
return true;
}
int main(int, char**) int main(int, char**)
{ {
...@@ -81,5 +111,7 @@ int main(int, char**) ...@@ -81,5 +111,7 @@ int main(int, char**)
static_assert(test_constexpr()); static_assert(test_constexpr());
#endif #endif
static_assert(test_noexcept(), "");
return 0; return 0;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment