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.
Details
- Reviewers
ldionne • Quuxplusone Mordante - Group Reviewers
Restricted Project - Commits
- rG0d450aa641f9: [libc++] P2401: conditional noexcept for std::exchange
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Thanks for working on this! It seems you use C++17 only code in C++14 mode.
libcxx/include/__utility/exchange.h | ||
---|---|---|
26–27 | is_nothrow_move_constructible_v requires C++17. | |
libcxx/test/std/utilities/utility/exchange/exchange.pass.cpp | ||
16–17 | Please update the synopsis. Here and in the <utility> header. | |
54 | Can you make a typedef for this type so the decltypes below aren't required. | |
114 | Maybe move this to line 105, so the static_assert test can be guarded by the TEST_STD_VER at line 106. |
libcxx/include/__utility/exchange.h | ||
---|---|---|
26–27 | Fixed, thanks! | |
libcxx/test/std/utilities/utility/exchange/exchange.pass.cpp | ||
16–17 | Updated the synopsis, including the note about constexpr after C++17 in the <utility> header. | |
54 | Added type aliases to clean things up. | |
114 | The above TEST_STD_VER is > 17 but since this noexcept goes back to C++14 (when std::exchange was introduced), I think it's best to leave it here. |
Requesting changes, but pretty minor ones. The idea LGTM in general.
libcxx/docs/Status/Cxx2bPapers.csv | ||
---|---|---|
39 | s/Complete/|Complete|/ | |
libcxx/include/__utility/exchange.h | ||
26–27 | I'd prefer to see the noexcept-clause broken onto the next line (and indented), for readability: _T1 exchange(_T1& __obj, _T2&& __new_value) noexcept(is_nothrow_move_constructible<_T1>::value && is_nothrow_assignable<_T1&, _T2>::value) There's also a pre-existing bogus extra space in _T2 && __new_value. | |
libcxx/test/std/utilities/utility/exchange/exchange.pass.cpp | ||
45 | Mildly weird that you're using move-construction but copy-assignment. (It'd be less weird if you were testing all 4-or-whatever permutations of move and copy operations, but you're not.) 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); }; (No need for Exchange in the name of the class, because this whole file is about std::exchange.) | |
49–64 | Contrary to @Mordante's request, I'd prefer to simplify this code until no typedef is needed. I'd write the whole function's body as simply { 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))); } |
A few small remarks remaining.
libcxx/include/utility | ||
---|---|---|
187 | Please add the constexpr in the signature. Please add noexcept in C++23. This only is required in C++23. Since it's allowed to strengthen noexcept I don't mind it available in earlier versions. | |
libcxx/test/std/utilities/utility/exchange/exchange.pass.cpp | ||
49–64 |
I'm fine with this version without typedefs, my main issue was the amount of decltypes in the original version. | |
114 | I see the test executes no code, otherwise it couldn't execute the test in constexpr until C++20. ASSERT_NOEXCEPT is just a static_assert. So there's no real need to test this function twice. |
LGTM provided the CI passes. (Some of our builders are currently offline, I already notified the maintainer of these nodes.)
ping @Quuxplusone. The test is as you proposed, but wanted your approval before I land this.
s/Complete/|Complete|/