This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
std::sub_match::compare(string_view) overloadSection: 28.6.8 [re.submatch] Status: New Submitter: Jonathan Wakely Opened: 2018-06-26 Last modified: 2024-10-03
Priority: 3
View all other issues in [re.submatch].
View all issues with New status.
Discussion:
std::sub_match::compare can be called with a basic_string or a pointer to a null-terminated
character sequence, but can't be called with a basic_string_view. To compare to a string_view
requires either conversion to basic_string (with a potential allocation) or a redundant call to
traits_type::length to calculate a length that is already known.
[2018-07-02, Jonathan comments and completes proposed wording]
To make the relational and equality operators for sub_match support string views I propose specifying
the semantics, not adding another 12 overloaded operators to namespace std, in addition to the 42
already there. This allows them to be implemented as "hidden friends" if the implementation so desires, or to
retain namespace-scope declaration if backwards compatibility with C++11 - C++17 is preferred.
[2018-07-20 Priority set to 3 after reflector discussion]
Previous resolution [SUPERSEDED]:
This wording is relative to N4750.
Change 28.6.3 [re.syn], header
<regex>synopsis, as indicated:#include <initializer_list> namespace std { […] using csub_match = sub_match<const char*>; using wcsub_match = sub_match<const wchar_t*>; using ssub_match = sub_match<string::const_iterator>; using wssub_match = sub_match<wstring::const_iterator>;// 28.6.8.3 [re.submatch.op], sub_match non-member operators template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); […] template<class BiIter> bool operator>=(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs);template<class charT, class ST, class BiIter> basic_ostream<charT, ST>& operator<<(basic_ostream<charT, ST>& os, const sub_match<BiIter>& m); […] }Change 28.6.8 [re.submatch], class template
sub_matchsynopsis, as indicated:namespace std { template<class BidirectionalIterator> class sub_match : public pair<BidirectionalIterator, BidirectionalIterator> { public: using value_type = typename iterator_traits<BidirectionalIterator>::value_type; […] int compare(const sub_match& s) const; int compare(const string_type& s) const; int compare(const value_type* s) const; }; }Change 28.6.8.2 [re.submatch.members] as indicated:
int compare(const value_type* s) const;-7- Returns:
str().compare(s).
Change sub-clause 28.6.8.3 [re.submatch.op] as indicated:
31.9.2
sub_matchnon-member operators [re.submatch.op]template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
-1- Returns:lhs.compare(rhs) == 0.[…]template<class BiIter> bool operator>=(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs);
-42- Returns:!(lhs < rhs).template<class charT, class ST, class BiIter> basic_ostream<charT, ST>& operator<<(basic_ostream<charT, ST>& os, const sub_match<BiIter>& m);-43- Returns:
os << m.str().
[2024-10-03; Jonathan rebases the wording on the latest WP]
The proposed resolution has been implemented and tested in libstdc++.
Proposed resolution:
This wording is relative to N4988.
Change 28.6.3 [re.syn], header <regex> synopsis, as indicated:
using csub_match = sub_match<const char*>; using wcsub_match = sub_match<const wchar_t*>; using ssub_match = sub_match<string::const_iterator>; using wssub_match = sub_match<wstring::const_iterator>; // 28.6.8.3 [re.submatch.op], sub_match non-member operators template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); template<class BiIter> bool operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); template<class BiIter, class ST, class SA> bool operator==( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); template<class BiIter, class ST, class SA> bool operator<=>( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type* rhs); template<class BiIter> bool operator<=>(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type* rhs); template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs); template<class BiIter> bool operator<=>(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs); template<class charT, class ST, class BiIter> basic_ostream<charT, ST>& operator<<(basic_ostream<charT, ST>& os, const sub_match<BiIter>& m);
Change 28.6.8 [re.submatch], class template sub_match synopsis, as indicated:
namespace std {
template<class BidirectionalIterator>
class sub_match : public pair<BidirectionalIterator, BidirectionalIterator> {
public:
using value_type =
typename iterator_traits<BidirectionalIterator>::value_type;
[…]
int compare(const sub_match& s) const;
int compare(const string_type& s) const;
int compare(const value_type* s) const;
};
}
Change 28.6.8.2 [re.submatch.members] as indicated:
int compare(const value_type* s) const;-7- Returns:
str().compare(s).
Change sub-clause 28.6.8.3 [re.submatch.op] as indicated:
32.8.3
sub_matchnon-member operators [re.submatch.op]-1- Let
SM-CAT(I)becompare_three_way_result_t<basic_string<typename iterator_traits<I>::value_type>>template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);-2- Returns:
lhs.compare(rhs) == 0.template<class BiIter> bool operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);-3- Returns:
static_cast<SM-CAT(BiIter)>(lhs.compare(rhs) <=> 0).template<class BiIter, class ST, class SA> bool operator==( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);-4- Returns:
lhs.compare(.typename sub_match<BiIter>::string_type(rhs.data(), rhs.size())) == 0template<class BiIter, class ST, class SA> auto operator<=>( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);-5- Returns:
static_cast<SM-CAT(BiIter)>(lhs.compare(typename sub_match<BiIter>::string_type(rhs.data(), rhs.size())) <=> 0 )