sub_match
comparison operatorsSection: 28.6.8.3 [re.submatch.op] Status: C++11 Submitter: Daniel Krügler Opened: 2009-07-25 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [re.submatch.op].
View all issues with C++11 status.
Discussion:
Several heterogeneous comparison operators of class template
sub_match
are specified by return clauses that are not valid
in general. E.g. 28.6.8.3 [re.submatch.op]/7:
template <class BiIter, class ST, class SA> bool operator==( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);Returns:
lhs == rhs.str()
.
The returns clause would be ill-formed for all cases where
ST != std::char_traits<iterator_traits<BiIter>::value_type>
or SA != std::allocator<iterator_traits<BiIter>::value_type>
.
The generic character of the comparison was intended, so
there are basically two approaches to fix the problem: The
first one would define the semantics of the comparison
using the traits class ST
(The semantic of basic_string::compare
is defined in terms of the compare function of the corresponding
traits class), the second one would define the semantics of the
comparison using the traits class
std::char_traits<iterator_traits<BiIter>::value_type>
which is essentially identical to
std::char_traits<sub_match<BiIter>::value_type>
I suggest to follow the second approach, because
this emphasizes the central role of the sub_match
object as part of the comparison and would also
make sure that a sub_match
comparison using some
basic_string<char_t, ..>
always is equivalent to
a corresponding comparison with a string literal
because of the existence of further overloads (beginning
from 28.6.8.3 [re.submatch.op]/19). If users really want to
take advantage of their own traits::compare
, they can
simply write a corresponding compare function that
does so.
[ Post-Rapperswil ]
The following update is a result of the discussion during the Rapperswil meeting, the P/R expresses all comparisons by
delegating to sub_match's compare functions. The processing is rather mechanical: Only ==
and <
where defined by referring to sub_match
's compare function, all remaining ones where replaced by the canonical
definitions in terms of these two.
Moved to Tentatively Ready after 5 positive votes on c++std-lib.
[ Adopted at 2010-11 Batavia ]
Proposed resolution:
The wording refers to N3126.
template <class BiIter, class ST, class SA> bool operator==( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);7 Returns:
.
lhs == rhs.str()rhs.compare(lhs.c_str()) == 0
template <class BiIter, class ST, class SA> bool operator!=( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);8 Returns:
.
lhs != rhs.str()!(lhs == rhs)
template <class BiIter, class ST, class SA> bool operator<( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);9 Returns:
.
lhs < rhs.str()rhs.compare(lhs.c_str()) > 0
template <class BiIter, class ST, class SA> bool operator>( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);10 Returns:
.
lhs > rhs.str()rhs < lhs
template <class BiIter, class ST, class SA> bool operator>=( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);11 Returns:
.
lhs >= rhs.str()!(lhs < rhs)
template <class BiIter, class ST, class SA> bool operator<=( const basic_string< typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs);12 Returns:
.
lhs <= rhs.str()!(rhs < lhs)
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);13 Returns:
.
lhs.str() == rhslhs.compare(rhs.c_str()) == 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);14 Returns:
.
lhs.str() != rhs!(lhs == 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);15 Returns:
.
lhs.str() < rhslhs.compare(rhs.c_str()) < 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);16 Returns:
.
lhs.str() > rhsrhs < lhs
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);17 Returns:
.
lhs.str() >= rhs!(lhs < 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);18 Returns:
.
lhs.str() <= rhs!(rhs < lhs)
template <class BiIter> bool operator==(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);19 Returns:
.
lhs == rhs.str()rhs.compare(lhs) == 0
template <class BiIter> bool operator!=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);20 Returns:
.
lhs != rhs.str()!(lhs == rhs)
template <class BiIter> bool operator<(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);21 Returns:
.
lhs < rhs.str()rhs.compare(lhs) > 0
template <class BiIter> bool operator>(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);22 Returns:
.
lhs > rhs.str()rhs < lhs
template <class BiIter> bool operator>=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);23 Returns:
.
lhs >= rhs.str()!(lhs < rhs)
template <class BiIter> bool operator<=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs);24 Returns:
.
lhs <= rhs.str()!(rhs < lhs)
template <class BiIter> bool operator==(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);25 Returns:
.
lhs.str() == rhslhs.compare(rhs) == 0
template <class BiIter> bool operator!=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);26 Returns:
.
lhs.str() != rhs!(lhs == rhs)
template <class BiIter> bool operator<(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);27 Returns:
.
lhs.str() < rhslhs.compare(rhs) < 0
template <class BiIter> bool operator>(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);28 Returns:
.
lhs.str() > rhsrhs < lhs
template <class BiIter> bool operator>=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);29 Returns:
.
lhs.str() >= rhs!(lhs < rhs)
template <class BiIter> bool operator<=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs);30 Returns:
.
lhs.str() <= rhs!(rhs < lhs)
template <class BiIter> bool operator==(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);
31 Returns:basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) == rhs.str()
.
31 Returns:rhs.compare(typename sub_match<BiIter>::string_type(1, lhs)) == 0
.
template <class BiIter> bool operator!=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);32 Returns:
.
basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) != rhs.str()!(lhs == rhs)
template <class BiIter> bool operator<(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);
33 Returns:basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) < rhs.str()
.
33 Returns:rhs.compare(typename sub_match<BiIter>::string_type(1, lhs)) > 0
.
template <class BiIter> bool operator>(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);34 Returns:
.
basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) > rhs.str()rhs < lhs
template <class BiIter> bool operator>=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);35 Returns:
.
basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) >= rhs.str()!(lhs < rhs)
template <class BiIter> bool operator<=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs);36 Returns:
.
basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) <= rhs.str()!(rhs < lhs)
template <class BiIter> bool operator==(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);
37 Returns:lhs.str() == basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)
.
37 Returns:lhs.compare(typename sub_match<BiIter>::string_type(1, rhs)) == 0
.
template <class BiIter> bool operator!=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);38 Returns:
.
lhs.str() != basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)!(lhs == rhs)
template <class BiIter> bool operator<(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);
39 Returns:lhs.str() < basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)
.
39 Returns:lhs.compare(typename sub_match<BiIter>::string_type(1, rhs)) < 0
.
template <class BiIter> bool operator>(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);40 Returns:
.
lhs.str() > basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)rhs < lhs
template <class BiIter> bool operator>=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);41 Returns:
.
lhs.str() >= basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)!(lhs < rhs)
template <class BiIter> bool operator<=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs);42 Returns:
.
lhs.str() <= basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)!(rhs < lhs)