//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// <regex>
// template <class BidirectionalIterator> class sub_match;
// Note in C++20 several of these operators have been removed and implicitly
// generated by the compiler using operator== and operator<=>.
// template <class BiIter>
// bool
// operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator!=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator<(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator<=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator>=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// 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);
//
// template <class BiIter>
// bool
// operator==(typename iterator_traits<BiIter>::value_type const* lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator!=(typename iterator_traits<BiIter>::value_type const* lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator<(typename iterator_traits<BiIter>::value_type const* lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator>(typename iterator_traits<BiIter>::value_type const* lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator>=(typename iterator_traits<BiIter>::value_type const* lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator<=(typename iterator_traits<BiIter>::value_type const* lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator==(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const* rhs);
//
// template <class BiIter>
// bool
// operator!=(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const* rhs);
//
// template <class BiIter>
// bool
// operator<(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const* rhs);
//
// template <class BiIter>
// bool
// operator>(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const* rhs);
//
// template <class BiIter>
// bool
// operator>=(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const* rhs);
//
// template <class BiIter>
// bool
// operator<=(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const* rhs);
//
// template <class BiIter>
// bool
// operator==(typename iterator_traits<BiIter>::value_type const& lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator!=(typename iterator_traits<BiIter>::value_type const& lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator<(typename iterator_traits<BiIter>::value_type const& lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator>(typename iterator_traits<BiIter>::value_type const& lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator>=(typename iterator_traits<BiIter>::value_type const& lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator<=(typename iterator_traits<BiIter>::value_type const& lhs,
// const sub_match<BiIter>& rhs);
//
// template <class BiIter>
// bool
// operator==(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const& rhs);
//
// template <class BiIter>
// bool
// operator!=(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const& rhs);
//
// template <class BiIter>
// bool
// operator<(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const& rhs);
//
// template <class BiIter>
// bool
// operator>(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const& rhs);
//
// template <class BiIter>
// bool
// operator>=(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const& rhs);
//
// template <class BiIter>
// bool
// operator<=(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const& rhs);
// Added in C++20
// template <class BiIter>
// auto
// operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
// template <class BiIter, class ST, class SA>
// auto
// operator<=>(const sub_match<BiIter>& lhs,
// const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
//
// template <class BiIter>
// auto
// operator<=>(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const* rhs);
//
// template <class BiIter>
// auto
// operator<=>(const sub_match<BiIter>& lhs,
// typename iterator_traits<BiIter>::value_type const& rhs);
#include <regex>
#include <array>
#include <cassert>
#include "constexpr_char_traits.h"
#include "make_string.h"
#include "test_comparisons.h"
#include "test_macros.h"
#define SV(S) MAKE_STRING_VIEW(CharT, S)
template <class CharT>
void
test(const std::basic_string<CharT>& x, const std::basic_string<CharT>& y, bool doCStrTests = true)
{
typedef std::basic_string<CharT> string;
typedef std::sub_match<typename string::const_iterator> sub_match;
#if TEST_STD_VER > 17
AssertOrderReturn<std::strong_ordering, sub_match>();
AssertOrderReturn<std::strong_ordering, sub_match, string>();
#else
AssertComparisonsReturnBool<sub_match>();
AssertComparisonsReturnBool<sub_match, string>();
#endif
sub_match sm1;
sm1.first = x.begin();
sm1.second = x.end();
sm1.matched = true;
sub_match sm2;
sm2.first = y.begin();
sm2.second = y.end();
sm2.matched = true;
assert(testComparisons(sm1, sm2, x == y, x < y));
assert(testComparisons(x, sm2, x == y, x < y));
assert(testComparisons(sm1, y, x == y, x < y));
#if TEST_STD_VER > 17
assert(testOrder(sm1, sm2, x <=> y));
assert(testOrder(x, sm2, x <=> y));
assert(testOrder(sm1, y, x <=> y));
#endif
if (doCStrTests) {
assert(testComparisons(x.c_str(), sm2, x == y, x < y));
assert(testComparisons(sm1, y.c_str(), x == y, x < y));
#if TEST_STD_VER > 17
assert(testOrder(x.c_str(), sm2, x <=> y));
assert(testOrder(sm1, y.c_str(), x <=> y));
#endif
}
assert(testComparisons(x[0], sm2, string(1, x[0]) == y, string(1, x[0]) < y));
assert(testComparisons(sm1, y[0], x == string(1, y[0]), x < string(1, y[0])));
#if TEST_STD_VER > 17
assert(testOrder(x[0], sm2, (string(1, x[0]) <=> y)));
assert(testOrder(sm1, y[0], x <=> (string(1, y[0]))));
#endif
}
#if TEST_STD_VER > 17
template <class CharT, class Ordering>
struct char_traits : public constexpr_char_traits<CharT> {
using comparison_category = Ordering;
};
template <class T, class Ordering = std::strong_ordering>
constexpr void test() {
AssertOrderAreNoexcept<T>();
AssertOrderReturn<Ordering, T>();
using CharT = typename T::value_type;
// sorted values
std::array s = [] {
std::array input{SV(""), SV("abc"), SV("abcdef")};
return std::array{
T{input[0].begin(), input[0].end()}, T{input[1].begin(), input[1].end()}, T{input[2].begin(), input[2].end()}};
}();
auto ctor = [](const T& string) {
std::sub_match<typename T::const_iterator> sm;
sm.first = string.begin();
sm.second = string.end();
sm.matched = true;
return sm;
};
std::array sm{ctor(s[0]), ctor(s[1]), ctor(s[2])};
for (std::size_t i = 0; i < s.size(); ++i) {
for (std::size_t j = 0; j < s.size(); ++j) {
assert(testOrder(s[i], sm[j], i == j ? Ordering::equivalent : i < j ? Ordering::less : Ordering::greater));
}
}
}
template <class CharT>
constexpr void test_all_orderings() {
test<std::basic_string<CharT>>(); // Strong ordering in its char_traits
test<std::basic_string<CharT, constexpr_char_traits<CharT>>,
std::weak_ordering>(); // No ordering in its char_traits
test<std::basic_string<CharT, char_traits<CharT, std::weak_ordering>>, std::weak_ordering>();
test<std::basic_string<CharT, char_traits<CharT, std::partial_ordering>>, std::partial_ordering>();
}
#endif // TEST_STD_VER > 17
int main(int, char**)
{
test(std::string("123"), std::string("123"));
test(std::string("1234"), std::string("123"));
test(std::string("123\000" "56", 6), std::string("123\000" "56", 6), false);
#if TEST_STD_VER > 17
test_all_orderings<char>();
#endif
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test(std::wstring(L"123"), std::wstring(L"123"));
test(std::wstring(L"1234"), std::wstring(L"123"));
test(std::wstring(L"123\000" L"56", 6), std::wstring(L"123\000" L"56", 6), false);
#if TEST_STD_VER > 17
test_all_orderings<wchar_t>();
#endif
#endif // TEST_HAS_NO_WIDE_CHARACTERS
return 0;
}