struct -> class normalization for matchers

This commit is contained in:
Martin Hořeňovský 2022-04-10 23:53:37 +02:00
parent 9abe49ec53
commit 1a56ba851b
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
6 changed files with 80 additions and 56 deletions

View File

@ -37,14 +37,18 @@ namespace Matchers {
template<typename T> template<typename T>
struct MatcherBase : MatcherUntypedBase { class MatcherBase : public MatcherUntypedBase {
public:
virtual bool match( T const& arg ) const = 0; virtual bool match( T const& arg ) const = 0;
}; };
namespace Detail { namespace Detail {
template<typename ArgT> template<typename ArgT>
struct MatchAllOf final : MatcherBase<ArgT> { class MatchAllOf final : public MatcherBase<ArgT> {
std::vector<MatcherBase<ArgT> const*> m_matchers;
public:
MatchAllOf() = default; MatchAllOf() = default;
MatchAllOf(MatchAllOf const&) = delete; MatchAllOf(MatchAllOf const&) = delete;
MatchAllOf& operator=(MatchAllOf const&) = delete; MatchAllOf& operator=(MatchAllOf const&) = delete;
@ -83,9 +87,6 @@ namespace Matchers {
rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
return CATCH_MOVE(rhs); return CATCH_MOVE(rhs);
} }
private:
std::vector<MatcherBase<ArgT> const*> m_matchers;
}; };
//! lvalue overload is intentionally deleted, users should //! lvalue overload is intentionally deleted, users should
@ -98,7 +99,9 @@ namespace Matchers {
MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete; MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete;
template<typename ArgT> template<typename ArgT>
struct MatchAnyOf final : MatcherBase<ArgT> { class MatchAnyOf final : public MatcherBase<ArgT> {
std::vector<MatcherBase<ArgT> const*> m_matchers;
public:
MatchAnyOf() = default; MatchAnyOf() = default;
MatchAnyOf(MatchAnyOf const&) = delete; MatchAnyOf(MatchAnyOf const&) = delete;
MatchAnyOf& operator=(MatchAnyOf const&) = delete; MatchAnyOf& operator=(MatchAnyOf const&) = delete;
@ -136,9 +139,6 @@ namespace Matchers {
rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
return CATCH_MOVE(rhs); return CATCH_MOVE(rhs);
} }
private:
std::vector<MatcherBase<ArgT> const*> m_matchers;
}; };
//! lvalue overload is intentionally deleted, users should //! lvalue overload is intentionally deleted, users should
@ -151,8 +151,10 @@ namespace Matchers {
MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete; MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete;
template<typename ArgT> template<typename ArgT>
struct MatchNotOf final : MatcherBase<ArgT> { class MatchNotOf final : public MatcherBase<ArgT> {
MatcherBase<ArgT> const& m_underlyingMatcher;
public:
explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ): explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ):
m_underlyingMatcher( underlyingMatcher ) m_underlyingMatcher( underlyingMatcher )
{} {}
@ -164,9 +166,6 @@ namespace Matchers {
std::string describe() const override { std::string describe() const override {
return "not " + m_underlyingMatcher.toString(); return "not " + m_underlyingMatcher.toString();
} }
private:
MatcherBase<ArgT> const& m_underlyingMatcher;
}; };
} // namespace Detail } // namespace Detail

View File

@ -17,7 +17,8 @@ namespace Matchers {
enum class FloatingPointKind : uint8_t; enum class FloatingPointKind : uint8_t;
} }
struct WithinAbsMatcher final : MatcherBase<double> { class WithinAbsMatcher final : public MatcherBase<double> {
public:
WithinAbsMatcher(double target, double margin); WithinAbsMatcher(double target, double margin);
bool match(double const& matchee) const override; bool match(double const& matchee) const override;
std::string describe() const override; std::string describe() const override;
@ -26,8 +27,11 @@ namespace Matchers {
double m_margin; double m_margin;
}; };
struct WithinUlpsMatcher final : MatcherBase<double> { class WithinUlpsMatcher final : public MatcherBase<double> {
WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType); public:
WithinUlpsMatcher( double target,
uint64_t ulps,
Detail::FloatingPointKind baseType );
bool match(double const& matchee) const override; bool match(double const& matchee) const override;
std::string describe() const override; std::string describe() const override;
private: private:
@ -42,7 +46,8 @@ namespace Matchers {
// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
// the same result if we do this for floats, as if we do this for // the same result if we do this for floats, as if we do this for
// doubles that were promoted from floats. // doubles that were promoted from floats.
struct WithinRelMatcher final : MatcherBase<double> { class WithinRelMatcher final : public MatcherBase<double> {
public:
WithinRelMatcher( double target, double epsilon ); WithinRelMatcher( double target, double epsilon );
bool match(double const& matchee) const override; bool match(double const& matchee) const override;
std::string describe() const override; std::string describe() const override;

View File

@ -26,39 +26,46 @@ namespace Matchers {
std::string m_str; std::string m_str;
}; };
struct StringMatcherBase : MatcherBase<std::string> { class StringMatcherBase : public MatcherBase<std::string> {
StringMatcherBase( StringRef operation, CasedString const& comparator ); protected:
std::string describe() const override;
CasedString m_comparator; CasedString m_comparator;
StringRef m_operation; StringRef m_operation;
public:
StringMatcherBase( StringRef operation,
CasedString const& comparator );
std::string describe() const override;
}; };
struct StringEqualsMatcher final : StringMatcherBase { class StringEqualsMatcher final : public StringMatcherBase {
public:
StringEqualsMatcher( CasedString const& comparator ); StringEqualsMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override; bool match( std::string const& source ) const override;
}; };
struct StringContainsMatcher final : StringMatcherBase { class StringContainsMatcher final : public StringMatcherBase {
public:
StringContainsMatcher( CasedString const& comparator ); StringContainsMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override; bool match( std::string const& source ) const override;
}; };
struct StartsWithMatcher final : StringMatcherBase { class StartsWithMatcher final : public StringMatcherBase {
public:
StartsWithMatcher( CasedString const& comparator ); StartsWithMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override; bool match( std::string const& source ) const override;
}; };
struct EndsWithMatcher final : StringMatcherBase { class EndsWithMatcher final : public StringMatcherBase {
public:
EndsWithMatcher( CasedString const& comparator ); EndsWithMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override; bool match( std::string const& source ) const override;
}; };
struct RegexMatcher final : MatcherBase<std::string> { class RegexMatcher final : public MatcherBase<std::string> {
std::string m_regex;
CaseSensitive m_caseSensitivity;
public:
RegexMatcher( std::string regex, CaseSensitive caseSensitivity ); RegexMatcher( std::string regex, CaseSensitive caseSensitivity );
bool match( std::string const& matchee ) const override; bool match( std::string const& matchee ) const override;
std::string describe() const override; std::string describe() const override;
private:
std::string m_regex;
CaseSensitive m_caseSensitivity;
}; };
//! Creates matcher that accepts strings that are exactly equal to `str` //! Creates matcher that accepts strings that are exactly equal to `str`

View File

@ -19,7 +19,8 @@
namespace Catch { namespace Catch {
namespace Matchers { namespace Matchers {
struct MatcherGenericBase : MatcherUntypedBase { class MatcherGenericBase : public MatcherUntypedBase {
public:
MatcherGenericBase() = default; MatcherGenericBase() = default;
virtual ~MatcherGenericBase(); // = default; virtual ~MatcherGenericBase(); // = default;
@ -119,7 +120,8 @@ namespace Matchers {
template<typename... MatcherTs> template<typename... MatcherTs>
struct MatchAllOfGeneric final : MatcherGenericBase { class MatchAllOfGeneric final : public MatcherGenericBase {
public:
MatchAllOfGeneric(MatchAllOfGeneric const&) = delete; MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete; MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
MatchAllOfGeneric(MatchAllOfGeneric&&) = default; MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
@ -137,8 +139,12 @@ namespace Matchers {
return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{}); return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
} }
// Has to be public to enable the concatenating operators
// below, because they are not friend of the RHS, only LHS,
// and thus cannot access private fields of RHS
std::array<void const*, sizeof...( MatcherTs )> m_matchers; std::array<void const*, sizeof...( MatcherTs )> m_matchers;
//! Avoids type nesting for `GenericAllOf && GenericAllOf` case //! Avoids type nesting for `GenericAllOf && GenericAllOf` case
template<typename... MatchersRHS> template<typename... MatchersRHS>
friend friend
@ -169,7 +175,8 @@ namespace Matchers {
template<typename... MatcherTs> template<typename... MatcherTs>
struct MatchAnyOfGeneric final : MatcherGenericBase { class MatchAnyOfGeneric final : public MatcherGenericBase {
public:
MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete; MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete; MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default; MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
@ -187,6 +194,10 @@ namespace Matchers {
return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{}); return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
} }
// Has to be public to enable the concatenating operators
// below, because they are not friend of the RHS, only LHS,
// and thus cannot access private fields of RHS
std::array<void const*, sizeof...( MatcherTs )> m_matchers; std::array<void const*, sizeof...( MatcherTs )> m_matchers;
//! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
@ -218,7 +229,10 @@ namespace Matchers {
template<typename MatcherT> template<typename MatcherT>
struct MatchNotOfGeneric final : MatcherGenericBase { class MatchNotOfGeneric final : public MatcherGenericBase {
MatcherT const& m_matcher;
public:
MatchNotOfGeneric(MatchNotOfGeneric const&) = delete; MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete; MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
MatchNotOfGeneric(MatchNotOfGeneric&&) = default; MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
@ -239,8 +253,6 @@ namespace Matchers {
friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) { friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
return matcher.m_matcher; return matcher.m_matcher;
} }
private:
MatcherT const& m_matcher;
}; };
} // namespace Detail } // namespace Detail

View File

@ -17,8 +17,10 @@ namespace Catch {
namespace Matchers { namespace Matchers {
template<typename T, typename Alloc> template<typename T, typename Alloc>
struct VectorContainsElementMatcher final : MatcherBase<std::vector<T, Alloc>> { class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> {
T const& m_comparator;
public:
VectorContainsElementMatcher(T const& comparator): VectorContainsElementMatcher(T const& comparator):
m_comparator(comparator) m_comparator(comparator)
{} {}
@ -35,13 +37,13 @@ namespace Matchers {
std::string describe() const override { std::string describe() const override {
return "Contains: " + ::Catch::Detail::stringify( m_comparator ); return "Contains: " + ::Catch::Detail::stringify( m_comparator );
} }
T const& m_comparator;
}; };
template<typename T, typename AllocComp, typename AllocMatch> template<typename T, typename AllocComp, typename AllocMatch>
struct ContainsMatcher final : MatcherBase<std::vector<T, AllocMatch>> { class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
std::vector<T, AllocComp> const& m_comparator;
public:
ContainsMatcher(std::vector<T, AllocComp> const& comparator): ContainsMatcher(std::vector<T, AllocComp> const& comparator):
m_comparator( comparator ) m_comparator( comparator )
{} {}
@ -67,13 +69,13 @@ namespace Matchers {
std::string describe() const override { std::string describe() const override {
return "Contains: " + ::Catch::Detail::stringify( m_comparator ); return "Contains: " + ::Catch::Detail::stringify( m_comparator );
} }
std::vector<T, AllocComp> const& m_comparator;
}; };
template<typename T, typename AllocComp, typename AllocMatch> template<typename T, typename AllocComp, typename AllocMatch>
struct EqualsMatcher final : MatcherBase<std::vector<T, AllocMatch>> { class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
std::vector<T, AllocComp> const& m_comparator;
public:
EqualsMatcher(std::vector<T, AllocComp> const& comparator): EqualsMatcher(std::vector<T, AllocComp> const& comparator):
m_comparator( comparator ) m_comparator( comparator )
{} {}
@ -93,12 +95,14 @@ namespace Matchers {
std::string describe() const override { std::string describe() const override {
return "Equals: " + ::Catch::Detail::stringify( m_comparator ); return "Equals: " + ::Catch::Detail::stringify( m_comparator );
} }
std::vector<T, AllocComp> const& m_comparator;
}; };
template<typename T, typename AllocComp, typename AllocMatch> template<typename T, typename AllocComp, typename AllocMatch>
struct ApproxMatcher final : MatcherBase<std::vector<T, AllocMatch>> { class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
std::vector<T, AllocComp> const& m_comparator;
mutable Catch::Approx approx = Catch::Approx::custom();
public:
ApproxMatcher(std::vector<T, AllocComp> const& comparator): ApproxMatcher(std::vector<T, AllocComp> const& comparator):
m_comparator( comparator ) m_comparator( comparator )
{} {}
@ -129,13 +133,13 @@ namespace Matchers {
approx.scale(static_cast<double>(newScale)); approx.scale(static_cast<double>(newScale));
return *this; return *this;
} }
std::vector<T, AllocComp> const& m_comparator;
mutable Catch::Approx approx = Catch::Approx::custom();
}; };
template<typename T, typename AllocComp, typename AllocMatch> template<typename T, typename AllocComp, typename AllocMatch>
struct UnorderedEqualsMatcher final : MatcherBase<std::vector<T, AllocMatch>> { class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
std::vector<T, AllocComp> const& m_target;
public:
UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target): UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target):
m_target(target) m_target(target)
{} {}
@ -149,15 +153,12 @@ namespace Matchers {
std::string describe() const override { std::string describe() const override {
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
} }
private:
std::vector<T, AllocComp> const& m_target;
}; };
// The following functions create the actual matcher objects. // The following functions create the actual matcher objects.
// This allows the types to be inferred // This allows the types to be inferred
//! Creates a matcher that matches vectors that contain all elements in `comparator` //! Creates a matcher that matches vectors that contain all elements in `comparator`
template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {

View File

@ -36,7 +36,7 @@ namespace Catch {
namespace Matchers { namespace Matchers {
template <typename ArgT> template <typename ArgT>
struct MatcherBase; class MatcherBase;
} }
using StringMatcher = Matchers::MatcherBase<std::string>; using StringMatcher = Matchers::MatcherBase<std::string>;