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|/