This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
Section: 32.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. 32.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 32.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).