From: Christopher Di Bella Date: Fri, 2 Apr 2021 21:33:39 +0000 (+0000) Subject: [libcxx] fixes `common_reference` requirement for `swappable_with` X-Git-Tag: llvmorg-14-init~10269 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cedd07df5136ba446be23dbd2ca7d29d7b82cd60;p=platform%2Fupstream%2Fllvm.git [libcxx] fixes `common_reference` requirement for `swappable_with` LWG3175 identifies that the `common_reference` requirement for `swappable_with` is over-constraining and doesn't need to concern itself with cv- or reference qualifiers. Differential Revision: https://reviews.llvm.org/D99817 --- diff --git a/libcxx/docs/Cxx2aStatusIssuesStatus.csv b/libcxx/docs/Cxx2aStatusIssuesStatus.csv index 064adf2..55d5126 100644 --- a/libcxx/docs/Cxx2aStatusIssuesStatus.csv +++ b/libcxx/docs/Cxx2aStatusIssuesStatus.csv @@ -194,7 +194,7 @@ "`3050 `__","Conversion specification problem in ``chrono::duration``\ constructor","Prague","","" "`3141 `__","``CopyConstructible``\ doesn't preserve source values","Prague","","" "`3150 `__","``UniformRandomBitGenerator``\ should validate ``min``\ and ``max``\ ","Prague","","" -"`3175 `__","The ``CommonReference``\ requirement of concept ``SwappableWith``\ is not satisfied in the example","Prague","","" +"`3175 `__","The ``CommonReference``\ requirement of concept ``SwappableWith``\ is not satisfied in the example","Prague","|Complete|","13.0" "`3194 `__","``ConvertibleTo``\ prose does not match code","Prague","","" "`3200 `__","``midpoint``\ should not constrain ``T``\ is complete","Prague","|Nothing To Do|","" "`3201 `__","``lerp``\ should be marked as ``noexcept``\ ","Prague","|Complete|","" diff --git a/libcxx/include/concepts b/libcxx/include/concepts index 200a177..6ce2fad 100644 --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -326,7 +326,7 @@ concept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; template concept swappable_with = - common_reference_with<_Tp&, _Up&> && + common_reference_with<_Tp, _Up> && requires(_Tp&& __t, _Up&& __u) { ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t)); ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u)); diff --git a/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp index 46e526d..e0772b5 100644 --- a/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -555,7 +556,7 @@ struct swappable_with_rvalue_ref_to_volatile_s3 { friend void swap(swappable_with_rvalue_ref_to_volatile_s3 volatile&&, s3 volatile&&); - operator s3 volatile &() volatile; + operator s3 volatile &&() volatile; }; static_assert( std::swappable_with()); } // namespace types_with_purpose -int main(int, char**) { return 0; } +namespace LWG3175 { +// Example taken directly from [concept.swappable] +template U> +constexpr void value_swap(T&& t, U&& u) { + std::ranges::swap(std::forward(t), std::forward(u)); +} + +template +constexpr void lv_swap(T& t1, T& t2) { + std::ranges::swap(t1, t2); +} + +namespace N { +struct A { + int m; +}; +struct Proxy { + A* a; + constexpr Proxy(A& a_) : a{&a_} {} + friend constexpr void swap(Proxy x, Proxy y) { + std::ranges::swap(*x.a, *y.a); + } +}; +constexpr Proxy proxy(A& a) { return Proxy{a}; } +} // namespace N + +[[nodiscard]] constexpr bool CheckRegression() { + int i = 1, j = 2; + lv_swap(i, j); + assert(i == 2 && j == 1); + + N::A a1 = {5}, a2 = {-5}; + value_swap(a1, proxy(a2)); + assert(a1.m == -5 && a2.m == 5); + return true; +} + +static_assert(CheckRegression()); +} // namespace LWG3175