// 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_VECTOR_HPP_INCLUDED #define CATCH_MATCHERS_VECTOR_HPP_INCLUDED #include #include #include namespace Catch { namespace Matchers { template class VectorContainsElementMatcher final : public MatcherBase> { T const& m_comparator; public: VectorContainsElementMatcher(T const& comparator): m_comparator(comparator) {} bool match(std::vector const& v) const override { for (auto const& el : v) { if (el == m_comparator) { return true; } } return false; } std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } }; template class ContainsMatcher final : public MatcherBase> { std::vector const& m_comparator; public: ContainsMatcher(std::vector const& comparator): m_comparator( comparator ) {} bool match(std::vector const& v) const override { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; for (auto const& comparator : m_comparator) { auto present = false; for (const auto& el : v) { if (el == comparator) { present = true; break; } } if (!present) { return false; } } return true; } std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } }; template class EqualsMatcher final : public MatcherBase> { std::vector const& m_comparator; public: EqualsMatcher(std::vector const& comparator): m_comparator( comparator ) {} bool match(std::vector const& v) const override { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector etc // - then just call that directly if ( m_comparator.size() != v.size() ) { return false; } for ( std::size_t i = 0; i < v.size(); ++i ) { if ( !( m_comparator[i] == v[i] ) ) { return false; } } return true; } std::string describe() const override { return "Equals: " + ::Catch::Detail::stringify( m_comparator ); } }; template class ApproxMatcher final : public MatcherBase> { std::vector const& m_comparator; mutable Catch::Approx approx = Catch::Approx::custom(); public: ApproxMatcher(std::vector const& comparator): m_comparator( comparator ) {} bool match(std::vector const& v) const override { if (m_comparator.size() != v.size()) return false; for (std::size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != approx(v[i])) return false; return true; } std::string describe() const override { return "is approx: " + ::Catch::Detail::stringify( m_comparator ); } template ::value>> ApproxMatcher& epsilon( T const& newEpsilon ) { approx.epsilon(static_cast(newEpsilon)); return *this; } template ::value>> ApproxMatcher& margin( T const& newMargin ) { approx.margin(static_cast(newMargin)); return *this; } template ::value>> ApproxMatcher& scale( T const& newScale ) { approx.scale(static_cast(newScale)); return *this; } }; template class UnorderedEqualsMatcher final : public MatcherBase> { std::vector const& m_target; public: UnorderedEqualsMatcher(std::vector const& target): m_target(target) {} bool match(std::vector const& vec) const override { if (m_target.size() != vec.size()) { return false; } return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); } std::string describe() const override { return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); } }; // The following functions create the actual matcher objects. // This allows the types to be inferred //! Creates a matcher that matches vectors that contain all elements in `comparator` template, typename AllocMatch = AllocComp> ContainsMatcher Contains( std::vector const& comparator ) { return ContainsMatcher(comparator); } //! Creates a matcher that matches vectors that contain `comparator` as an element template> VectorContainsElementMatcher VectorContains( T const& comparator ) { return VectorContainsElementMatcher(comparator); } //! Creates a matcher that matches vectors that are exactly equal to `comparator` template, typename AllocMatch = AllocComp> EqualsMatcher Equals( std::vector const& comparator ) { return EqualsMatcher(comparator); } //! Creates a matcher that matches vectors that `comparator` as an element template, typename AllocMatch = AllocComp> ApproxMatcher Approx( std::vector const& comparator ) { return ApproxMatcher(comparator); } //! Creates a matcher that matches vectors that is equal to `target` modulo permutation template, typename AllocMatch = AllocComp> UnorderedEqualsMatcher UnorderedEquals(std::vector const& target) { return UnorderedEqualsMatcher(target); } } // namespace Matchers } // namespace Catch #endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED