// Copyright Catch2 Authors // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) // SPDX-License-Identifier: BSL-1.0 #ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED #define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED #include #include #include #include namespace Catch { namespace Matchers { /** * Matcher for checking that an element contains the same * elements in the same order */ template class RangeEqualsMatcher final : public MatcherGenericBase { TargetRangeLike m_desired; Equality m_predicate; public: template RangeEqualsMatcher( TargetRangeLike2&& range, Equality2&& predicate ): m_desired( CATCH_FORWARD( range ) ), m_predicate( CATCH_FORWARD( predicate ) ) {} template bool match( RangeLike&& rng ) const { auto rng_start = begin( rng ); const auto rng_end = end( rng ); auto target_start = begin( m_desired ); const auto target_end = end( m_desired ); while (rng_start != rng_end && target_start != target_end) { if (!m_predicate(*rng_start, *target_start)) { return false; } ++rng_start; ++target_start; } return rng_start == rng_end && target_start == target_end; } std::string describe() const override { return "elements are " + Catch::Detail::stringify( m_desired ); } }; /** * Matcher for checking that an element contains the same * elements (but not necessarily in the same order) */ template class UnorderedRangeEqualsMatcher final : public MatcherGenericBase { TargetRangeLike m_desired; Equality m_predicate; public: template UnorderedRangeEqualsMatcher( TargetRangeLike2&& range, Equality2&& predicate ): m_desired( CATCH_FORWARD( range ) ), m_predicate( CATCH_FORWARD( predicate ) ) {} template bool match( RangeLike&& rng ) const { using std::begin; using std::end; return Catch::Detail::is_permutation( begin( m_desired ), end( m_desired ), begin( rng ), end( rng ), m_predicate ); } std::string describe() const override { return "unordered elements are " + ::Catch::Detail::stringify( m_desired ); } }; /** * Creates a matcher that checks if all elements in a range are equal * to all elements in another range. * * Uses `std::equal_to` to do the comparison */ template std::enable_if_t::value, RangeEqualsMatcher>> RangeEquals( RangeLike&& range ) { return { CATCH_FORWARD( range ), std::equal_to<>{} }; } /** * Creates a matcher that checks if all elements in a range are equal * to all elements in another range. * * Uses to provided predicate `predicate` to do the comparisons */ template RangeEqualsMatcher RangeEquals( RangeLike&& range, Equality&& predicate ) { return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; } /** * Creates a matcher that checks if all elements in a range are equal * to all elements in another range, in some permutation * * Uses `std::equal_to` to do the comparison */ template std::enable_if_t< !Detail::is_matcher::value, UnorderedRangeEqualsMatcher>> UnorderedRangeEquals( RangeLike&& range ) { return { CATCH_FORWARD( range ), std::equal_to<>{} }; } /** * Creates a matcher that checks if all elements in a range are equal * to all elements in another range, in some permutation. * * Uses to provided predicate `predicate` to do the comparisons */ template UnorderedRangeEqualsMatcher UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) { return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; } } // namespace Matchers } // namespace Catch #endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED