diff --git a/stl/inc/regex b/stl/inc/regex index dc5c484cf54..42069bb43b9 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -983,9 +983,19 @@ public: using char_type = typename iterator_traits<_BidIt>::value_type; using string_type = basic_string; - match_results() : _Org(), _Ready(false) {} + match_results() = default; - explicit match_results(const _Alloc& _Al) : _Org(), _Ready(false), _Matches(_Al) {} + explicit match_results(const _Alloc& _Al) : _Matches(_Al) {} + + match_results(const match_results& _Other, const _Alloc& _Al) + : _Org(_Other._Org), _Ready(_Other._Ready), _Matches(_Other._Matches, _Al), _Prefix(_Other._Prefix), + _Suffix(_Other._Suffix), _Null_elem(_Other._Null_elem) {} + + match_results(match_results&& _Other, const _Alloc& _Al) noexcept( + conjunction_v>) // strengthened + : _Org(_STD move(_Other._Org)), _Ready(_Other._Ready), _Matches(_STD move(_Other._Matches), _Al), + _Prefix(_STD move(_Other._Prefix)), _Suffix(_STD move(_Other._Suffix)), + _Null_elem(_STD move(_Other._Null_elem)) {} _NODISCARD bool ready() const noexcept /* strengthened */ { return _Ready; @@ -1126,8 +1136,8 @@ public: return _Matches[_Sub]; } - _BidIt _Org; - bool _Ready; + _BidIt _Org = _BidIt(); + bool _Ready = false; private: _MyCont _Matches; diff --git a/tests/std/tests/VSO_0000000_regex_interface/test.cpp b/tests/std/tests/VSO_0000000_regex_interface/test.cpp index 0703637e4be..c057696eb3a 100644 --- a/tests/std/tests/VSO_0000000_regex_interface/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_interface/test.cpp @@ -10,6 +10,11 @@ #include #include #include +#include + +#if _HAS_CXX17 +#include +#endif // _HAS_CXX17 using namespace std; using namespace std::regex_constants; @@ -156,6 +161,41 @@ void test_dev10_505773_default_constructed_regex_should_not_match_empty_string() assert(!regex_match("", r)); } +void test_LWG_2195_allocator_extended_ctors_for_match_result() { + constexpr char input[] = {'a', 'b', '\0', 'c', 'd'}; + const regex pattern(".(.).*"); + + { + cmatch results; + assert(regex_match(begin(input), end(input), results, pattern)); + + cmatch r1{results, cmatch::allocator_type{}}; + assert(r1 == results); + + cmatch r2{move(results), cmatch::allocator_type{}}; + assert(r2 == r1); + + // strengthened exception specification + static_assert(is_nothrow_constructible_v, + "Allocator-extended move construction should be noexcept when the allocator is stateless."); + } +#if _HAS_CXX17 + { + pmr::cmatch results; + assert(regex_match(begin(input), end(input), results, pattern)); + + pmr::cmatch r1{results, pmr::cmatch::allocator_type{}}; + assert(r1 == results); + + pmr::cmatch r2{move(results), pmr::cmatch::allocator_type{}}; + assert(r2 == r1); + + static_assert(!is_nothrow_constructible_v, + "Allocator-extended move construction shouldn't be noexcept when the allocator is stateful."); + } +#endif // _HAS_CXX17 +} + template void test_LWG_2217_sub_match_should_not_slice_nulls() { // LWG-2217: "operator==(sub_match, string) slices on embedded '\0's" @@ -393,6 +433,7 @@ int main() { test_dev10_900584_should_handle_quantified_alternates(); test_devdiv_903531_regex_should_have_correct_suffix_matching(); test_dev10_505773_default_constructed_regex_should_not_match_empty_string(); + test_LWG_2195_allocator_extended_ctors_for_match_result(); test_LWG_2217_sub_match_should_not_slice_nulls(); test_LWG_2217_sub_match_should_not_slice_nulls>(); test_VSO_177524_sub_match_compare_should_not_construct_unnecessary_basic_strings();