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

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<BiIter>::value_type, ST, SA>& lhs,
   >        const sub_match<BiIter>& 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<BiIter>::value_type, ST, SA>& lhs,
   >        const sub_match<BiIter>& 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<BiIter>::value_type, ST, SA>& lhs,
   >        const sub_match<BiIter>& 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<BiIter>::value_type, ST, SA>& lhs,
   >        const sub_match<BiIter>& 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<BiIter>::value_type, ST, SA>& lhs,
   >      const sub_match<BiIter>& 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<BiIter>::value_type, ST, SA>& lhs,
   >        const sub_match<BiIter>& 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<BiIter>& lhs,
   >        const basic_string<
   >          typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);

   > 13 Returns: `lhs.str() == rhslhs.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<BiIter>& lhs,
   >        const basic_string<
   >          typename iterator_traits<BiIter>::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<BiIter>& lhs,
   >        const basic_string<
   >          typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);

   > 15 Returns: `lhs.str() < rhslhs.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<BiIter>& lhs,
    >        const basic_string<
    >          typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);

    > 16 Returns: `lhs.str() > rhsrhs < lhs`.

11. Change 28.9.2 [re.submatch.op]/17 as indicated:

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

12. Change 28.9.2 [re.submatch.op]/18 as indicated:

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

13. Change 28.9.2 [re.submatch.op]/19 as indicated:

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

14. Change 28.9.2 [re.submatch.op]/20 as indicated:

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

15. Change 28.9.2 [re.submatch.op]/21 as indicated:

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

16. Change 28.9.2 [re.submatch.op]/22 as indicated:

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

17. Change 28.9.2 [re.submatch.op]/23 as indicated:

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

18. Change 28.9.2 [re.submatch.op]/24 as indicated:

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

19. Change 28.9.2 [re.submatch.op]/25 as indicated:

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

20. Change 28.9.2 [re.submatch.op]/26 as indicated:

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

21. Change 28.9.2 [re.submatch.op]/27 as indicated:

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

22. Change 28.9.2 [re.submatch.op]/28 as indicated:

    >     template <class BiIter>
    >      bool operator>(const sub_match<BiIter>& lhs,
    >        typename iterator_traits<BiIter>::value_type const* rhs);

    > 28 Returns: `lhs.str() > rhsrhs < lhs`.

23. Change 28.9.2 [re.submatch.op]/29 as indicated:

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

24. Change 28.9.2 [re.submatch.op]/30 as indicated:

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

25. Change 28.9.2 [re.submatch.op]/31 as indicated:

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

26. Change 28.9.2 [re.submatch.op]/32 as indicated:

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

27. Change 28.9.2 [re.submatch.op]/33 as indicated:

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

28. Change 28.9.2 [re.submatch.op]/34 as indicated:

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

29. Change 28.9.2 [re.submatch.op]/35 as indicated:

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

30. Change 28.9.2 [re.submatch.op]/36 as indicated:

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

31. Change 28.9.2 [re.submatch.op]/37 as indicated:

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

32. Change 28.9.2 [re.submatch.op]/38 as indicated:

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

33. Change 28.9.2 [re.submatch.op]/39 as indicated:

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

34. Change 28.9.2 [re.submatch.op]/40 as indicated:

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

35. Change 28.9.2 [re.submatch.op]/41 as indicated:

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

36. Change 28.9.2 [re.submatch.op]/42 as indicated:

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