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>
struct MatcherBase : MatcherUntypedBase {
class MatcherBase : public MatcherUntypedBase {
public:
virtual bool match( T const& arg ) const = 0;
};
namespace Detail {
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(MatchAllOf const&) = delete;
MatchAllOf& operator=(MatchAllOf const&) = delete;
@ -83,9 +87,6 @@ namespace Matchers {
rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
return CATCH_MOVE(rhs);
}
private:
std::vector<MatcherBase<ArgT> const*> m_matchers;
};
//! 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;
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(MatchAnyOf const&) = delete;
MatchAnyOf& operator=(MatchAnyOf const&) = delete;
@ -136,9 +139,6 @@ namespace Matchers {
rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
return CATCH_MOVE(rhs);
}
private:
std::vector<MatcherBase<ArgT> const*> m_matchers;
};
//! 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;
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 ):
m_underlyingMatcher( underlyingMatcher )
{}
@ -164,9 +166,6 @@ namespace Matchers {
std::string describe() const override {
return "not " + m_underlyingMatcher.toString();
}
private:
MatcherBase<ArgT> const& m_underlyingMatcher;
};
} // namespace Detail

View File

@ -17,7 +17,8 @@ namespace Matchers {
enum class FloatingPointKind : uint8_t;
}
struct WithinAbsMatcher final : MatcherBase<double> {
class WithinAbsMatcher final : public MatcherBase<double> {
public:
WithinAbsMatcher(double target, double margin);
bool match(double const& matchee) const override;
std::string describe() const override;
@ -26,8 +27,11 @@ namespace Matchers {
double m_margin;
};
struct WithinUlpsMatcher final : MatcherBase<double> {
WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType);
class WithinUlpsMatcher final : public MatcherBase<double> {
public:
WithinUlpsMatcher( double target,
uint64_t ulps,
Detail::FloatingPointKind baseType );
bool match(double const& matchee) const override;
std::string describe() const override;
private:
@ -42,8 +46,9 @@ namespace Matchers {
// |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
// doubles that were promoted from floats.
struct WithinRelMatcher final : MatcherBase<double> {
WithinRelMatcher(double target, double epsilon);
class WithinRelMatcher final : public MatcherBase<double> {
public:
WithinRelMatcher( double target, double epsilon );
bool match(double const& matchee) const override;
std::string describe() const override;
private:

View File

@ -26,39 +26,46 @@ namespace Matchers {
std::string m_str;
};
struct StringMatcherBase : MatcherBase<std::string> {
StringMatcherBase( StringRef operation, CasedString const& comparator );
std::string describe() const override;
class StringMatcherBase : public MatcherBase<std::string> {
protected:
CasedString m_comparator;
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 );
bool match( std::string const& source ) const override;
};
struct StringContainsMatcher final : StringMatcherBase {
class StringContainsMatcher final : public StringMatcherBase {
public:
StringContainsMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override;
};
struct StartsWithMatcher final : StringMatcherBase {
class StartsWithMatcher final : public StringMatcherBase {
public:
StartsWithMatcher( CasedString const& comparator );
bool match( std::string const& source ) const override;
};
struct EndsWithMatcher final : StringMatcherBase {
class EndsWithMatcher final : public StringMatcherBase {
public:
EndsWithMatcher( CasedString const& comparator );
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 );
bool match( std::string const& matchee ) 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`

View File

@ -19,7 +19,8 @@
namespace Catch {
namespace Matchers {
struct MatcherGenericBase : MatcherUntypedBase {
class MatcherGenericBase : public MatcherUntypedBase {
public:
MatcherGenericBase() = default;
virtual ~MatcherGenericBase(); // = default;
@ -119,7 +120,8 @@ namespace Matchers {
template<typename... MatcherTs>
struct MatchAllOfGeneric final : MatcherGenericBase {
class MatchAllOfGeneric final : public MatcherGenericBase {
public:
MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
@ -137,7 +139,11 @@ namespace Matchers {
return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
}
std::array<void const*, sizeof...(MatcherTs)> m_matchers;
// 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;
//! Avoids type nesting for `GenericAllOf && GenericAllOf` case
template<typename... MatchersRHS>
@ -169,7 +175,8 @@ namespace Matchers {
template<typename... MatcherTs>
struct MatchAnyOfGeneric final : MatcherGenericBase {
class MatchAnyOfGeneric final : public MatcherGenericBase {
public:
MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
@ -187,7 +194,11 @@ namespace Matchers {
return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
}
std::array<void const*, sizeof...(MatcherTs)> m_matchers;
// 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;
//! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
template<typename... MatchersRHS>
@ -218,7 +229,10 @@ namespace Matchers {
template<typename MatcherT>
struct MatchNotOfGeneric final : MatcherGenericBase {
class MatchNotOfGeneric final : public MatcherGenericBase {
MatcherT const& m_matcher;
public:
MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
@ -239,8 +253,6 @@ namespace Matchers {
friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
return matcher.m_matcher;
}
private:
MatcherT const& m_matcher;
};
} // namespace Detail

View File

@ -17,8 +17,10 @@ namespace Catch {
namespace Matchers {
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):
m_comparator(comparator)
{}
@ -35,13 +37,13 @@ namespace Matchers {
std::string describe() const override {
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
}
T const& m_comparator;
};
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):
m_comparator( comparator )
{}
@ -67,13 +69,13 @@ namespace Matchers {
std::string describe() const override {
return "Contains: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector<T, AllocComp> const& m_comparator;
};
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):
m_comparator( comparator )
{}
@ -93,12 +95,14 @@ namespace Matchers {
std::string describe() const override {
return "Equals: " + ::Catch::Detail::stringify( m_comparator );
}
std::vector<T, AllocComp> const& m_comparator;
};
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):
m_comparator( comparator )
{}
@ -129,13 +133,13 @@ namespace Matchers {
approx.scale(static_cast<double>(newScale));
return *this;
}
std::vector<T, AllocComp> const& m_comparator;
mutable Catch::Approx approx = Catch::Approx::custom();
};
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):
m_target(target)
{}
@ -149,15 +153,12 @@ namespace Matchers {
std::string describe() const override {
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
}
private:
std::vector<T, AllocComp> const& 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 T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {

View File

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