[libc++] Implement LWG-3204: `sub_match::swap` only swaps the base class
authorIgor Zhukov <fsb4000@yandex.ru>
Sat, 25 Feb 2023 14:43:37 +0000 (21:43 +0700)
committerIgor Zhukov <fsb4000@yandex.ru>
Sat, 25 Feb 2023 14:43:37 +0000 (21:43 +0700)
Reviewed By: Mordante, JMazurkiewicz, #libc

Differential Revision: https://reviews.llvm.org/D144629

libcxx/docs/Status/Cxx2bIssues.csv
libcxx/include/regex
libcxx/test/std/re/re.submatch/re.submatch.members/swap.pass.cpp [new file with mode: 0644]

index f03e118..1e7a611 100644 (file)
 "`3811 <https://wg21.link/LWG3811>`__","``views::as_const`` on ``ref_view<T>`` should return ``ref_view<const T>``","February 2023","","","|ranges|"
 "`3820 <https://wg21.link/LWG3820>`__","``cartesian_product_view::iterator::prev`` is not quite right","February 2023","","","|ranges|"
 "`3825 <https://wg21.link/LWG3825>`__","Missing compile-time argument ``id`` check in ``basic_format_parse_context::next_arg_id``","February 2023","","","|format|"
-"`3204 <https://wg21.link/LWG3204>`__","``sub_match::swap`` only swaps the base class","February 2023","","",""
+"`3204 <https://wg21.link/LWG3204>`__","``sub_match::swap`` only swaps the base class","February 2023","|Complete|","17.0",""
 "`3733 <https://wg21.link/LWG3733>`__","``ranges::to`` misuses ``cpp17-input-iterator``","February 2023","","","|ranges|"
 "`3742 <https://wg21.link/LWG3742>`__","``deque::prepend_range`` needs to permute","February 2023","","","|ranges|"
 "`3790 <https://wg21.link/LWG3790>`__","`P1467 <https://wg21.link/P1467>`__ accidentally changed ``nexttoward``'s signature","February 2023","","",""
index 15c2103..1fe93a1 100644 (file)
@@ -225,6 +225,8 @@ public:
     int compare(const sub_match& s) const;
     int compare(const string_type& s) const;
     int compare(const value_type* s) const;
+
+    void swap(sub_match& s) noexcept(see below);
 };
 
 typedef sub_match<const char*>             csub_match;
@@ -770,6 +772,7 @@ typedef regex_token_iterator<wstring::const_iterator> wsregex_token_iterator;
 #include <__iterator/wrap_iter.h>
 #include <__locale>
 #include <__memory_resource/polymorphic_allocator.h>
+#include <__type_traits/is_swappable.h>
 #include <__utility/move.h>
 #include <__utility/pair.h>
 #include <__utility/swap.h>
@@ -5008,6 +5011,16 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     int compare(const value_type* __s) const
         {return str().compare(__s);}
+
+    _LIBCPP_HIDE_FROM_ABI
+    void swap(sub_match& __s)
+#ifndef _LIBCPP_CXX03_LANG
+    _NOEXCEPT(__is_nothrow_swappable<_BidirectionalIterator>::value)
+#endif // _LIBCPP_CXX03_LANG
+    {
+        this->pair<_BidirectionalIterator, _BidirectionalIterator>::swap(__s);
+        std::swap(matched, __s.matched);
+    }
 };
 
 template <class _BiIter>
diff --git a/libcxx/test/std/re/re.submatch/re.submatch.members/swap.pass.cpp b/libcxx/test/std/re/re.submatch/re.submatch.members/swap.pass.cpp
new file mode 100644 (file)
index 0000000..9e93370
--- /dev/null
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <regex>
+
+// template <class BidirectionalIterator> class sub_match;
+
+// void swap(sub_match& s) noexcept(see below);
+
+#include <regex>
+#include <cassert>
+#include "test_macros.h"
+
+int main(int, char**) {
+  {
+    using CharT      = char;
+    using SM         = std::sub_match<const CharT*>;
+    const CharT s1[] = {'1', '2', '3', 0};
+    SM sm1;
+    sm1.first   = s1;
+    sm1.second  = s1 + 3;
+    sm1.matched = true;
+
+    SM sm2;
+    const CharT s2[] = {'c', 'a', 't', 0};
+    sm2.first        = s2;
+    sm2.second       = s2 + 3;
+    sm2.matched      = false;
+
+    sm1.swap(sm2);
+
+    assert(sm1.first == s2);
+    assert(sm1.second == s2 + 3);
+    assert(!sm1.matched);
+
+    assert(sm2.first == s1);
+    assert(sm2.second == s1 + 3);
+    assert(sm2.matched);
+
+    ASSERT_NOEXCEPT(sm1.swap(sm2));
+  }
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  {
+    using CharT      = wchar_t;
+    using SM         = std::sub_match<const CharT*>;
+    const CharT s1[] = {L'1', L'2', L'3', 0};
+    SM sm1;
+    sm1.first   = s1;
+    sm1.second  = s1 + 3;
+    sm1.matched = true;
+
+    SM sm2;
+    const CharT s2[] = {L'c', L'a', L't', 0};
+    sm2.first        = s2;
+    sm2.second       = s2 + 3;
+    sm2.matched      = false;
+
+    sm1.swap(sm2);
+
+    assert(sm1.first == s2);
+    assert(sm1.second == s2 + 3);
+    assert(!sm1.matched);
+
+    assert(sm2.first == s1);
+    assert(sm2.second == s1 + 3);
+    assert(sm2.matched);
+
+    ASSERT_NOEXCEPT(sm1.swap(sm2));
+  }
+#endif
+}