Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Comment thread
Andor233 marked this conversation as resolved.
}
#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\LWG2381_num_get_floating_point
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;
Comment thread
StephanTLavavej marked this conversation as resolved.
}
};


// 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());
}