Issue 1181: Invalid sub_match comparison operators (original) (raw)
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.
1181. Invalid sub_match comparison operators
Section: 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 templatesub_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::value_type, ST, SA>& lhs, const sub_match& rhs);
Returns:
lhs == rhs.str().
The returns clause would be ill-formed for all cases whereST != 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::compareis 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::value_type>
which is essentially identical to
std::char_traits<sub_match::value_type>
I suggest to follow the second approach, because this emphasizes the central role of the sub_matchobject as part of the comparison and would also make sure that a sub_match comparison using somebasic_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.
- Change 28.9.2 [re.submatch.op]/7 as indicated:
template <class BiIter, class ST, class SA>
bool operator==(
const basic_string<
typename iterator_traits::value_type, ST, SA>& lhs,
const sub_match& rhs);7 Returns:
~~lhs == rhs.str()~~rhs.compare(lhs.c_str()) == 0. - Change 28.9.2 [re.submatch.op]/8 as indicated:
template <class BiIter, class ST, class SA>
bool operator!=(
const basic_string<
typename iterator_traits::value_type, ST, SA>& lhs,
const sub_match& rhs);8 Returns:
~~lhs != rhs.str()~~!(lhs == rhs). - Change 28.9.2 [re.submatch.op]/9 as indicated:
template <class BiIter, class ST, class SA>
bool operator<(
const basic_string<
typename iterator_traits::value_type, ST, SA>& lhs,
const sub_match& rhs);9 Returns:
~~lhs < rhs.str()~~rhs.compare(lhs.c_str()) > 0. - Change 28.9.2 [re.submatch.op]/10 as indicated:
template <class BiIter, class ST, class SA>
bool operator>(
const basic_string<
typename iterator_traits::value_type, ST, SA>& lhs,
const sub_match& rhs);10 Returns:
~~lhs > rhs.str()~~rhs < lhs. - Change 28.9.2 [re.submatch.op]/11 as indicated:
template <class BiIter, class ST, class SA>
bool operator>=(
const basic_string<
typename iterator_traits::value_type, ST, SA>& lhs,
const sub_match& rhs);11 Returns:
~~lhs >= rhs.str()~~!(lhs < rhs). - Change 28.9.2 [re.submatch.op]/12 as indicated:
template <class BiIter, class ST, class SA>
bool operator<=(
const basic_string<
typename iterator_traits::value_type, ST, SA>& lhs,
const sub_match& rhs);12 Returns:
~~lhs <= rhs.str()~~!(rhs < lhs). - Change 28.9.2 [re.submatch.op]/13 as indicated:
template <class BiIter, class ST, class SA>
bool operator==(const sub_match& lhs,
const basic_string<
typename iterator_traits::value_type, ST, SA>& rhs);13 Returns:
~~lhs.str() == rhs~~lhs.compare(rhs.c_str()) == 0. - Change 28.9.2 [re.submatch.op]/14 as indicated:
template <class BiIter, class ST, class SA>
bool operator!=(const sub_match& lhs,
const basic_string<
typename iterator_traits::value_type, ST, SA>& rhs);14 Returns:
~~lhs.str() != rhs~~!(lhs == rhs). - Change 28.9.2 [re.submatch.op]/15 as indicated:
template <class BiIter, class ST, class SA>
bool operator<(const sub_match& lhs,
const basic_string<
typename iterator_traits::value_type, ST, SA>& rhs);15 Returns:
~~lhs.str() < rhs~~lhs.compare(rhs.c_str()) < 0. - Change 28.9.2 [re.submatch.op]/16 as indicated:
template <class BiIter, class ST, class SA>
bool operator>(const sub_match& lhs,
const basic_string<
typename iterator_traits::value_type, ST, SA>& rhs);16 Returns:
~~lhs.str() > rhs~~rhs < lhs. - Change 28.9.2 [re.submatch.op]/17 as indicated:
template <class BiIter, class ST, class SA>
bool operator>=(const sub_match& lhs,
const basic_string<
typename iterator_traits::value_type, ST, SA>& rhs);17 Returns:
~~lhs.str() >= rhs~~!(lhs < rhs). - Change 28.9.2 [re.submatch.op]/18 as indicated:
template <class BiIter, class ST, class SA>
bool operator<=(const sub_match& lhs,
const basic_string<
typename iterator_traits::value_type, ST, SA>& rhs);18 Returns:
~~lhs.str() <= rhs~~!(rhs < lhs). - Change 28.9.2 [re.submatch.op]/19 as indicated:
template
bool operator==(typename iterator_traits::value_type const* lhs,
const sub_match& rhs);19 Returns:
~~lhs == rhs.str()~~rhs.compare(lhs) == 0. - Change 28.9.2 [re.submatch.op]/20 as indicated:
template
bool operator!=(typename iterator_traits::value_type const* lhs,
const sub_match& rhs);20 Returns:
~~lhs != rhs.str()~~!(lhs == rhs). - Change 28.9.2 [re.submatch.op]/21 as indicated:
template
bool operator<(typename iterator_traits::value_type const* lhs,
const sub_match& rhs);21 Returns:
~~lhs < rhs.str()~~rhs.compare(lhs) > 0. - Change 28.9.2 [re.submatch.op]/22 as indicated:
template
bool operator>(typename iterator_traits::value_type const* lhs,
const sub_match& rhs);22 Returns:
~~lhs > rhs.str()~~rhs < lhs. - Change 28.9.2 [re.submatch.op]/23 as indicated:
template
bool operator>=(typename iterator_traits::value_type const* lhs,
const sub_match& rhs);23 Returns:
~~lhs >= rhs.str()~~!(lhs < rhs). - Change 28.9.2 [re.submatch.op]/24 as indicated:
template
bool operator<=(typename iterator_traits::value_type const* lhs,
const sub_match& rhs);24 Returns:
~~lhs <= rhs.str()~~!(rhs < lhs). - Change 28.9.2 [re.submatch.op]/25 as indicated:
template
bool operator==(const sub_match& lhs,
typename iterator_traits::value_type const* rhs);25 Returns:
~~lhs.str() == rhs~~lhs.compare(rhs) == 0. - Change 28.9.2 [re.submatch.op]/26 as indicated:
template
bool operator!=(const sub_match& lhs,
typename iterator_traits::value_type const* rhs);26 Returns:
~~lhs.str() != rhs~~!(lhs == rhs). - Change 28.9.2 [re.submatch.op]/27 as indicated:
template
bool operator<(const sub_match& lhs,
typename iterator_traits::value_type const* rhs);27 Returns:
~~lhs.str() < rhs~~lhs.compare(rhs) < 0. - Change 28.9.2 [re.submatch.op]/28 as indicated:
template
bool operator>(const sub_match& lhs,
typename iterator_traits::value_type const* rhs);28 Returns:
~~lhs.str() > rhs~~rhs < lhs. - Change 28.9.2 [re.submatch.op]/29 as indicated:
template
bool operator>=(const sub_match& lhs,
typename iterator_traits::value_type const* rhs);29 Returns:
~~lhs.str() >= rhs~~!(lhs < rhs). - Change 28.9.2 [re.submatch.op]/30 as indicated:
template
bool operator<=(const sub_match& lhs,
typename iterator_traits::value_type const* rhs);30 Returns:
~~lhs.str() <= rhs~~!(rhs < lhs). - Change 28.9.2 [re.submatch.op]/31 as indicated:
template
bool operator==(typename iterator_traits::value_type const& lhs,
const sub_match& 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. - Change 28.9.2 [re.submatch.op]/32 as indicated:
template
bool operator!=(typename iterator_traits::value_type const& lhs,
const sub_match& rhs);32 Returns:
~~basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) != rhs.str()~~!(lhs == rhs). - Change 28.9.2 [re.submatch.op]/33 as indicated:
template
bool operator<(typename iterator_traits::value_type const& lhs,
const sub_match& 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. - Change 28.9.2 [re.submatch.op]/34 as indicated:
template
bool operator>(typename iterator_traits::value_type const& lhs,
const sub_match& rhs);34 Returns:
~~basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) > rhs.str()~~rhs < lhs. - Change 28.9.2 [re.submatch.op]/35 as indicated:
template
bool operator>=(typename iterator_traits::value_type const& lhs,
const sub_match& rhs);35 Returns:
~~basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) >= rhs.str()~~!(lhs < rhs). - Change 28.9.2 [re.submatch.op]/36 as indicated:
template
bool operator<=(typename iterator_traits::value_type const& lhs,
const sub_match& rhs);36 Returns:
~~basic_string<typename iterator_traits<BiIter>::value_type>(1, lhs) <= rhs.str()~~!(rhs < lhs). - Change 28.9.2 [re.submatch.op]/37 as indicated:
template
bool operator==(const sub_match& lhs,
typename iterator_traits::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. - Change 28.9.2 [re.submatch.op]/38 as indicated:
template
bool operator!=(const sub_match& lhs,
typename iterator_traits::value_type const& rhs);38 Returns:
~~lhs.str() != basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)~~!(lhs == rhs). - Change 28.9.2 [re.submatch.op]/39 as indicated:
template
bool operator<(const sub_match& lhs,
typename iterator_traits::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. - Change 28.9.2 [re.submatch.op]/40 as indicated:
template
bool operator>(const sub_match& lhs,
typename iterator_traits::value_type const& rhs);40 Returns:
~~lhs.str() > basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)~~rhs < lhs. - Change 28.9.2 [re.submatch.op]/41 as indicated:
template
bool operator>=(const sub_match& lhs,
typename iterator_traits::value_type const& rhs);41 Returns:
~~lhs.str() >= basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)~~!(lhs < rhs). - Change 28.9.2 [re.submatch.op]/42 as indicated:
template
bool operator<=(const sub_match& lhs,
typename iterator_traits::value_type const& rhs);42 Returns:
~~lhs.str() <= basic_string<typename iterator_traits<BiIter>::value_type>(1, rhs)~~!(rhs < lhs).