Created on 2018-06-26.00:00:00 last changed 1 month ago
Proposed resolution:
This wording is relative to n4988.
Change [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>;
// [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, class ST>
bool operator==(
const sub_match<BiIter>& lhs,
const basic_string_view<typename iterator_traits<BiIter>::value_type, ST>& rhs);
template<class BiIter, class ST>
bool operator<=>(
const sub_match<BiIter>& lhs,
const basic_string_view<typename iterator_traits<BiIter>::value_type, ST>& 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 [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; int compare(basic_string_view<value_type> s) const; }; }
Change [re.submatch.members] as indicated:
int compare(const value_type* s) const;-7- Returns: str().compare(s).
int compare(basic_string_view<value_type> s) const;-?- Returns: str().compare(s).
Change sub-clause [re.submatch.op] as indicated:
32.8.3 sub_match non-member operators [re.submatch.op]
-1- Let
SV(I)
bebasic_string_view<typename iterator_traits<I>::value_type>
and letSM-CAT(I)
becompare_three_way_result_t<
basic_string<typename iterator_traits<I>::value_type>SV(I)>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_typeSV(BiIter)(rhs.data(), rhs.size())) == 0.template<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_typeSV(BiIter)(rhs.data(), rhs.size())) <=> 0 )template<class BiIter, class ST> bool operator==( const sub_match<BiIter>& lhs, const basic_string_view<typename iterator_traits<BiIter>::value_type, ST>& rhs);-?- Returns: lhs.compare(SV(BiIter)(rhs.data(), rhs.size())) == 0.
template<class BiIter, class ST> auto operator<=>( const sub_match<BiIter>& lhs, const basic_string_view<typename iterator_traits<BiIter>::value_type, ST>& rhs);-?- Returns:
static_cast<SM-CAT(BiIter)>(lhs.compare(SV(BiIter)(rhs.data(), rhs.size())) <=> 0)
.
[ 2024-10-03; Jonathan rebases the wording on the latest WP ]
The proposed resolution has been implemented and tested in libstdc++.
[ 2018-07-20 Priority set to 3 after reflector discussion ]
This wording is relative to N4750.
Change [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>;// [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 [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; int compare(basic_string_view<value_type> s) const; }; }
Change [re.submatch.members] as indicated:
int compare(const value_type* s) const;-7- Returns: str().compare(s).
int compare(basic_string_view<value_type> s) const;-?- Returns: str().compare(s).
Change sub-clause [re.submatch.op] as indicated:
31.9.2 sub_match non-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().
Class template sub_match provides overloaded relational operators ([expr.rel]) and equality operators ([expr.eq]) for comparisons with another sub_match, with a string, or with a single character. The expressions shown in Table ?? are valid when one of the operands is a type S, that is a specialization of sub_match, and the other expression is one of:
(?.?) — a value x of a type S, in which case STR(x) is x.str();
(?.?) — a value x of type basic_string<S::value_type, T, A> for any types T and A, in which case STR(x) is basic_string_view<S::value_type>(x.data(), x.length());
(?.?) — a value x of type basic_string_view<S::value_type, T> for any type T, in which case STR(x) is basic_string_view<S::value_type>(x.data(), x.length());
(?.?) — a value x of a type convertible to const S::value_type*, in which case STR(x) is basic_string_view<S::value_type>(x);
(?.?) — a value x of type convertible to S::value_type, in which case STR(x) is basic_string_view<S::value_type>(&x, 1).
Table ?? — sub_match comparisons Expression Return type Operational
semanticss == t bool STR(s).compare(STR(t)) == 0 s != t bool STR(s).compare(STR(t)) != 0 s < t bool STR(s).compare(STR(t)) < 0 s > t bool STR(s).compare(STR(t)) > 0 s <= t bool STR(s).compare(STR(t)) <= 0 s >= t bool STR(s).compare(STR(t)) >= 0
[ 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.
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.
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-10-03 19:34:11 | admin | set | messages: + msg14420 |
2018-07-20 21:06:57 | admin | set | messages: + msg10033 |
2018-07-04 20:07:55 | admin | set | messages: + msg10010 |
2018-06-27 18:25:17 | admin | set | messages: + msg9993 |
2018-06-26 00:00:00 | admin | create |