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.

  1. 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.

  2. 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).

  3. 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.

  4. 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.

  5. 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).

  6. 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).

  7. 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.

  8. 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).

  9. 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.

  10. 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.

  11. 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).

  12. 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).

  13. 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.

  14. 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).

  15. 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.

  16. 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.

  17. 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).

  18. 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).

  19. 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.

  20. 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).

  21. 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.

  22. 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.

  23. 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).

  24. 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).

  25. 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.

  26. 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).

  27. 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.

  28. 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.

  29. 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).

  30. 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).

  31. 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.

  32. 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).

  33. 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.

  34. 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.

  35. 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).

  36. 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).