Skip to content

Commit

Permalink
<utility>: Remove self swap check from pair. (#4674)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
  • Loading branch information
Andor233 and StephanTLavavej committed May 21, 2024
1 parent d1489f2 commit c8f45be
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 8 deletions.
12 changes: 4 additions & 8 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -441,21 +441,17 @@ struct pair { // store a pair of values
_CONSTEXPR20 void swap(pair& _Right) noexcept(
_Is_nothrow_swappable<_Ty1>::value && _Is_nothrow_swappable<_Ty2>::value) {
using _STD swap;
if (this != _STD addressof(_Right)) {
swap(first, _Right.first); // intentional ADL
swap(second, _Right.second); // intentional ADL
}
swap(first, _Right.first); // intentional ADL
swap(second, _Right.second); // intentional ADL
}

#if _HAS_CXX23
template <int = 0> // see GH-3013
constexpr void swap(const pair& _Right) const
noexcept(is_nothrow_swappable_v<const _Ty1> && is_nothrow_swappable_v<const _Ty2>) {
using _STD swap;
if (this != _STD addressof(_Right)) {
swap(first, _Right.first); // intentional ADL
swap(second, _Right.second); // intentional ADL
}
swap(first, _Right.first); // intentional ADL
swap(second, _Right.second); // intentional ADL
}
#endif // _HAS_CXX23

Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ tests\GH_004201_chrono_formatter
tests\GH_004275_seeking_fancy_iterators
tests\GH_004388_unordered_meow_operator_equal
tests\GH_004477_mdspan_warning_5246
tests\GH_004597_self_swap
tests\GH_004618_mixed_operator_usage_keeps_statistical_properties
tests\GH_004618_normal_distribution_avoids_resets
tests\GH_004657_expected_constraints_permissive
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/GH_004597_self_swap/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
90 changes: 90 additions & 0 deletions tests/std/tests/GH_004597_self_swap/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cassert>
#include <utility>

struct swap_counter {
unsigned int* pcnt_ = nullptr;

friend _CONSTEXPR20 void swap(swap_counter& lhs, swap_counter& rhs) noexcept {
assert(lhs.pcnt_ != nullptr);
assert(rhs.pcnt_ != nullptr);
std::swap(lhs.pcnt_, rhs.pcnt_);
++*lhs.pcnt_;
++*rhs.pcnt_;
}

_CONSTEXPR20 bool operator==(unsigned int x) const {
assert(pcnt_ != nullptr);
return *pcnt_ == x;
}
};


// Test GH-4597 "<utility>: Side effects in self-swaps of pair are skipped"
_CONSTEXPR20 bool test_gh_4597() {
{
unsigned int cnt{};
std::pair<swap_counter, int> pr{swap_counter{&cnt}, 10};
pr.swap(pr);
assert(cnt == 2u);
assert(pr.first == 2u);
assert(pr.second == 10);
}

{
unsigned int cnt{};
std::pair<swap_counter, int> p1{swap_counter{&cnt}, 10};
std::pair<swap_counter, int> p2{swap_counter{&cnt}, 11};
p1.swap(p2);
assert(cnt == 2u);
assert(p1.first == 2u);
assert(p1.second == 11);
assert(p2.first == 2u);
assert(p2.second == 10);
}

{
unsigned int c1{};
unsigned int c2{2};
std::pair<swap_counter, int> p1{swap_counter{&c1}, 11};
std::pair<swap_counter, int> p2{swap_counter{&c2}, 13};
p1.swap(p2);
assert(c1 == 1u);
assert(c2 == 3u);
assert(p1.first == 3u);
assert(p1.second == 13);
assert(p2.first == 1u);
assert(p2.second == 11);
}

#if _HAS_CXX23
{
unsigned int c1{};
unsigned int c2{2};
int i1 = 11;
int i2 = 13;
swap_counter s1{&c1};
swap_counter s2{&c2};
const std::pair<swap_counter&, int&> p1{s1, i1};
const std::pair<swap_counter&, int&> p2{s2, i2};
p1.swap(p2);
assert(c1 == 1u);
assert(c2 == 3u);
assert(p1.first == 3u);
assert(p1.second == 13);
assert(p2.first == 1u);
assert(p2.second == 11);
}
#endif // _HAS_CXX23

return true;
}

int main() {
#if _HAS_CXX20
static_assert(test_gh_4597());
#endif // _HAS_CXX20
assert(test_gh_4597());
}

0 comments on commit c8f45be

Please sign in to comment.