Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorLeitwolf112026-10-11 02:56:25 +0300
committerLeitwolf112026-10-11 02:56:25 +0300
commit1f78d8903c2fb18afea8c3055f8df83d8c60d9b5 (patch)
treed76f5945311828511e3ea55712487f21fbf8f70f /src
parent5633c5c98ec073ae938253bcfc72430d5d9aee89 (diff)
downloadcatch3-1f78d8903c2fb18afea8c3055f8df83d8c60d9b5.tar.gz
Backport Catch2 3.16.1
Review Catch2 devel through 08092139210881f01a34e60c5f2fd6afa0ea4024, the commit of 3.16.1, and apply the eleven changes since the last reviewed revision in upstream order: d7683484 better message when a reporter cannot be initialized ea5020f0 custom argument validation in every first-party reporter aa01559e throwing-reporter test also throws in assertionEnded 45cd3987 noexcept on handleUnexpectedInflightException 6adbd539 MSVC optimizations enabled again after the benchmark headers e87f2882 no quadratic scaling for NTTP test registration 73d546cd REQUIRE expands its arguments fewer times under GCC and Clang b710039a decomposer operators as plain functions f899467b type-erased streaming of reconstructed expressions 8f0e70ca retired macos-14 runner dropped 08092139 version 3.16.1 and its release notes All of them applied to the sources without a conflict. The amalgamated distribution under extras/ conflicted because it is generated; it is generated again from the sources of this repository, which also brings it up to date with fork changes it had not picked up: the list-based stream pool, the Clang diagnostic boundary and the cassert include. No file under src/Progmasoft changes. The fork-owned texts that name the engine version say 3.16.1, and docs/upstream-status.md records the review. Upstream files keep their names, licenses and compiler options. Built with Clang 22 on Windows and tested: 148 of 149 tests pass. The one that fails, Reporters::CrashInJunitReporter, fails the same way on devel without this change with that compiler.
Diffstat (limited to 'src')
-rw-r--r--src/catch2/benchmark/catch_optimizer.hpp2
-rw-r--r--src/catch2/catch_session.cpp12
-rw-r--r--src/catch2/catch_session.hpp1
-rw-r--r--src/catch2/catch_version.cpp2
-rw-r--r--src/catch2/catch_version_macros.hpp2
-rw-r--r--src/catch2/internal/catch_assertion_handler.cpp2
-rw-r--r--src/catch2/internal/catch_assertion_handler.hpp15
-rw-r--r--src/catch2/internal/catch_decomposer.cpp7
-rw-r--r--src/catch2/internal/catch_decomposer.hpp342
-rw-r--r--src/catch2/internal/catch_preprocessor.hpp4
-rw-r--r--src/catch2/internal/catch_test_macro_impl.hpp16
-rw-r--r--src/catch2/matchers/internal/catch_matchers_impl.hpp17
-rw-r--r--src/catch2/reporters/catch_reporter_automake.cpp9
-rw-r--r--src/catch2/reporters/catch_reporter_automake.hpp6
-rw-r--r--src/catch2/reporters/catch_reporter_compact.cpp7
-rw-r--r--src/catch2/reporters/catch_reporter_compact.hpp6
-rw-r--r--src/catch2/reporters/catch_reporter_console.cpp1
-rw-r--r--src/catch2/reporters/catch_reporter_helpers.cpp13
-rw-r--r--src/catch2/reporters/catch_reporter_helpers.hpp13
-rw-r--r--src/catch2/reporters/catch_reporter_json.cpp2
-rw-r--r--src/catch2/reporters/catch_reporter_junit.cpp4
-rw-r--r--src/catch2/reporters/catch_reporter_sonarqube.cpp10
-rw-r--r--src/catch2/reporters/catch_reporter_sonarqube.hpp9
-rw-r--r--src/catch2/reporters/catch_reporter_tap.cpp8
-rw-r--r--src/catch2/reporters/catch_reporter_tap.hpp6
-rw-r--r--src/catch2/reporters/catch_reporter_teamcity.cpp8
-rw-r--r--src/catch2/reporters/catch_reporter_teamcity.hpp8
-rw-r--r--src/catch2/reporters/catch_reporter_xml.cpp2
28 files changed, 311 insertions, 223 deletions
diff --git a/src/catch2/benchmark/catch_optimizer.hpp b/src/catch2/benchmark/catch_optimizer.hpp
index 5535b2a2..281256a3 100644
--- a/src/catch2/benchmark/catch_optimizer.hpp
+++ b/src/catch2/benchmark/catch_optimizer.hpp
@@ -46,7 +46,7 @@ namespace Catch {
*reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
}
// TODO equivalent keep_memory()
-#if defined(_MSVC_VER)
+#if defined(_MSC_VER)
#pragma optimize("", on)
#endif
diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp
index 1c993ce1..34fd2809 100644
--- a/src/catch2/catch_session.cpp
+++ b/src/catch2/catch_session.cpp
@@ -458,7 +458,17 @@ namespace Catch {
getCurrentMutableContext().setConfig(m_config.get());
// Create reporter(s) so we can route listings through them
- auto reporter = prepareReporters(m_config.get());
+ IEventListenerPtr reporter;
+ CATCH_TRY {
+ auto reporter_ = prepareReporters( m_config.get() );
+ swap( reporter, reporter_ );
+ }
+#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
+ catch ( std::exception& ex ) {
+ Catch::cerr() << "Error when creating reporter: " << ex.what() << '\n' << std::flush;
+ return ReporterConstructionErrorExitCode;
+ }
+#endif
auto const& invalidSpecs = m_config->testSpec().getInvalidSpecs();
if ( !invalidSpecs.empty() ) {
diff --git a/src/catch2/catch_session.hpp b/src/catch2/catch_session.hpp
index 23fc6f80..4da7c66f 100644
--- a/src/catch2/catch_session.hpp
+++ b/src/catch2/catch_session.hpp
@@ -22,6 +22,7 @@ namespace Catch {
constexpr int UnmatchedTestSpecExitCode = 3;
constexpr int AllTestsSkippedExitCode = 4;
constexpr int InvalidTestSpecExitCode = 5;
+ constexpr int ReporterConstructionErrorExitCode = 6;
constexpr int TestFailureExitCode = 42;
class Session : Detail::NonCopyable {
diff --git a/src/catch2/catch_version.cpp b/src/catch2/catch_version.cpp
index d0b44d72..cc332bc2 100644
--- a/src/catch2/catch_version.cpp
+++ b/src/catch2/catch_version.cpp
@@ -36,7 +36,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 3, 16, 0, "", 0 );
+ static Version version( 3, 16, 1, "", 0 );
return version;
}
diff --git a/src/catch2/catch_version_macros.hpp b/src/catch2/catch_version_macros.hpp
index 3219afb2..241928ab 100644
--- a/src/catch2/catch_version_macros.hpp
+++ b/src/catch2/catch_version_macros.hpp
@@ -10,6 +10,6 @@
#define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 16
-#define CATCH_VERSION_PATCH 0
+#define CATCH_VERSION_PATCH 1
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
diff --git a/src/catch2/internal/catch_assertion_handler.cpp b/src/catch2/internal/catch_assertion_handler.cpp
index 79d5dcd8..e028c371 100644
--- a/src/catch2/internal/catch_assertion_handler.cpp
+++ b/src/catch2/internal/catch_assertion_handler.cpp
@@ -61,7 +61,7 @@ namespace Catch {
}
}
- void AssertionHandler::handleUnexpectedInflightException() {
+ void AssertionHandler::handleUnexpectedInflightException() noexcept {
m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
}
diff --git a/src/catch2/internal/catch_assertion_handler.hpp b/src/catch2/internal/catch_assertion_handler.hpp
index 93a70b1a..4b7607ad 100644
--- a/src/catch2/internal/catch_assertion_handler.hpp
+++ b/src/catch2/internal/catch_assertion_handler.hpp
@@ -59,7 +59,20 @@ namespace Catch {
void handleUnexpectedExceptionNotThrown();
void handleExceptionNotThrownAsExpected();
void handleThrowingCallSkipped();
- void handleUnexpectedInflightException();
+
+ // Marking this as `noexcept` gives us measurable improvement
+ // in optimized compilation times. Making it `noexcept` changes
+ // what happens if the underlying code throws, **but** the only
+ // way this can throw is if the reporter itself throws from
+ // `assertionEnded`. However, in such case the process is going
+ // to abort anyway, because we will enter `assertionEnded` again
+ // from the (noexcept) destructor of `AssertionHandler` above.
+ // In the future, all reporter event handlers will be marked
+ // `noexcept` to make this limitation explicit.
+ void handleUnexpectedInflightException() noexcept;
+ // Ideally we could extend the logic above to more of the handle*
+ // function, but right now it would worsen the behaviour of
+ // preexisting custom reporters that throw from event handlers.
void complete();
diff --git a/src/catch2/internal/catch_decomposer.cpp b/src/catch2/internal/catch_decomposer.cpp
index 17a7bc95..e702c745 100644
--- a/src/catch2/internal/catch_decomposer.cpp
+++ b/src/catch2/internal/catch_decomposer.cpp
@@ -10,13 +10,6 @@
namespace Catch {
- void ITransientExpression::streamReconstructedExpression(
- std::ostream& os ) const {
- // We can't make this function pure virtual to keep ITransientExpression
- // constexpr, so we write error message instead
- os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression";
- }
-
void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
if( lhs.size() + rhs.size() < 40 &&
lhs.find('\n') == std::string::npos &&
diff --git a/src/catch2/internal/catch_decomposer.hpp b/src/catch2/internal/catch_decomposer.hpp
index ff628482..9c004b02 100644
--- a/src/catch2/internal/catch_decomposer.hpp
+++ b/src/catch2/internal/catch_decomposer.hpp
@@ -164,28 +164,27 @@ namespace Catch {
struct always_false : std::false_type {};
class ITransientExpression {
+ //! Type-erased streaming function for the derived expression
+ using StreamFn = void ( * )( void const*, std::ostream& );
+
+ StreamFn m_streamFn;
bool m_isBinaryExpression;
bool m_result;
- protected:
- ~ITransientExpression() = default;
-
public:
constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
constexpr auto getResult() const -> bool { return m_result; }
- //! This function **has** to be overridden by the derived class.
- virtual void streamReconstructedExpression( std::ostream& os ) const;
-
- constexpr ITransientExpression( bool isBinaryExpression, bool result )
- : m_isBinaryExpression( isBinaryExpression ),
- m_result( result )
- {}
- constexpr ITransientExpression( ITransientExpression const& ) = default;
- constexpr ITransientExpression& operator=( ITransientExpression const& ) = default;
+ constexpr ITransientExpression( StreamFn streamFn,
+ bool isBinaryExpression,
+ bool result ):
+ m_streamFn( streamFn ),
+ m_isBinaryExpression( isBinaryExpression ),
+ m_result( result ) {}
- friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
- expr.streamReconstructedExpression(out);
+ friend std::ostream& operator<<( std::ostream& out,
+ ITransientExpression const& expr ) {
+ expr.m_streamFn( &expr, out );
return out;
}
};
@@ -198,87 +197,67 @@ namespace Catch {
StringRef m_op;
RhsT m_rhs;
- void streamReconstructedExpression( std::ostream &os ) const override {
- formatReconstructedExpression
- ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
+ static void streamFn( void const* self, std::ostream& out ) {
+ auto const& expr = *static_cast<BinaryExpr const*>(
+ static_cast<ITransientExpression const*>( self ) );
+ formatReconstructedExpression(
+ out,
+ Catch::Detail::stringify( expr.m_lhs ),
+ expr.m_op,
+ Catch::Detail::stringify( expr.m_rhs ) );
}
public:
constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
- : ITransientExpression{ true, comparisonResult },
+ : ITransientExpression{ &streamFn, true, comparisonResult },
m_lhs( lhs ),
m_op( op ),
m_rhs( rhs )
{}
+ };
- template<typename T>
- auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
-
- template<typename T>
- auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
-
- template<typename T>
- auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
-
- template<typename T>
- auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
-
- template<typename T>
- auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
-
- template<typename T>
- auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
-
- template<typename T>
- auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
+#define CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( op ) \
+ template <typename LhsT, typename RhsT, typename T> \
+ auto operator op( BinaryExpr<LhsT, RhsT> const&, T ) \
+ ->BinaryExpr<LhsT, RhsT const&> const { \
+ static_assert( always_false<T>::value, \
+ "chained comparisons are not supported inside " \
+ "assertions, wrap the expression inside " \
+ "parentheses, or decompose it" ); \
+ }
- template<typename T>
- auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
- static_assert(always_false<T>::value,
- "chained comparisons are not supported inside assertions, "
- "wrap the expression inside parentheses, or decompose it");
- }
- };
+ /*
+ * The operators are **intentionally** not hidden friends.
+ *
+ * If they were hidden friends, all of them would get stamped out when
+ * a `BinaryExpr` is instantiated with a new type. In practice, only
+ * few operators are used for each different `BinaryExpr<LhsT, RhsT>`,
+ * so this avoids bunch of wasted work.
+ */
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( && )
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( || )
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( == )
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( != )
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( > )
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( < )
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( >= )
+ CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR( <= )
+
+#undef CATCH_INTERNAL_DEFINE_BINARY_EXPR_OPERATOR
template<typename LhsT>
class UnaryExpr final : public ITransientExpression {
LhsT m_lhs;
- void streamReconstructedExpression( std::ostream &os ) const override {
- os << Catch::Detail::stringify( m_lhs );
+ static void streamFn( void const* self, std::ostream& os ) {
+ auto const& expr = *static_cast<UnaryExpr const*>(
+ static_cast<ITransientExpression const*>( self ) );
+ os << Catch::Detail::stringify( expr.m_lhs );
}
public:
explicit constexpr UnaryExpr( LhsT lhs )
- : ITransientExpression{ false, static_cast<bool>(lhs) },
+ : ITransientExpression{ &streamFn, false, static_cast<bool>(lhs) },
m_lhs( lhs )
{}
};
@@ -290,153 +269,186 @@ namespace Catch {
public:
explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
+ // We rely on reference collapsing if LhsT is already a reference.
+ // Used in the out-of-class decomposition operators
+ constexpr LhsT& getLhs() { return m_lhs; }
+
+ constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
+ return UnaryExpr<LhsT>{ m_lhs };
+ }
+ };
+
+/*
+ * The comparison operators are **intentionally** not hidden friends.
+ *
+ * If they were hidden friends, all of them would get stamped out when
+ * a `ExprLhs` is instantiated with a new type. In practice, only few
+ * operators are used for each different `ExprLhs<T>`, so this avoids
+ * a lot of wasted work.
+ */
#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op ) \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT&& rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
Detail::negation<capture_by_value< \
Detail::RemoveCVRef_t<RhsT>>>>::value, \
BinaryExpr<LhsT, RhsT const&>> { \
- return { \
- static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
+ return { static_cast<bool>( lhs.getLhs() op rhs ), \
+ lhs.getLhs(), \
+ #op##_sr, \
+ rhs }; \
} \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
capture_by_value<RhsT>>::value, \
BinaryExpr<LhsT, RhsT>> { \
- return { \
- static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
+ return { static_cast<bool>( lhs.getLhs() op rhs ), \
+ lhs.getLhs(), \
+ #op##_sr, \
+ rhs }; \
} \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction< \
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
- Detail::is_eq_0_comparable<LhsT>, \
- /* We allow long because we want `ptr op NULL` to be accepted */ \
+ Detail::is_eq_0_comparable<LhsT>, /* We allow long because we \
+ want `ptr op NULL` to be \
+ accepted */ \
Detail::disjunction<std::is_same<RhsT, int>, \
std::is_same<RhsT, long>>>::value, \
BinaryExpr<LhsT, RhsT>> { \
if ( rhs != 0 ) { throw_test_failure_exception(); } \
- return { \
- static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
+ return { static_cast<bool>( lhs.getLhs() op 0 ), \
+ lhs.getLhs(), \
+ #op##_sr, \
+ rhs }; \
} \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction< \
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
- Detail::is_eq_0_comparable<RhsT>, \
- /* We allow long because we want `ptr op NULL` to be accepted */ \
+ Detail::is_eq_0_comparable<RhsT>, /* We allow long because we \
+ want `ptr op NULL` to be \
+ accepted */ \
Detail::disjunction<std::is_same<LhsT, int>, \
std::is_same<LhsT, long>>>::value, \
BinaryExpr<LhsT, RhsT>> { \
- if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
- return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
+ if ( lhs.getLhs() != 0 ) { throw_test_failure_exception(); } \
+ return { static_cast<bool>( 0 op rhs ), lhs.getLhs(), #op##_sr, rhs }; \
}
- CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
- CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != )
-
- #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
+ CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
+ CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != )
+#undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT&& rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
Detail::negation<capture_by_value< \
Detail::RemoveCVRef_t<RhsT>>>>::value, \
BinaryExpr<LhsT, RhsT const&>> { \
- return { \
- static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
+ return { static_cast<bool>( lhs.getLhs() op rhs ), \
+ lhs.getLhs(), \
+ #op##_sr, \
+ rhs }; \
} \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
capture_by_value<RhsT>>::value, \
BinaryExpr<LhsT, RhsT>> { \
- return { \
- static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
+ return { static_cast<bool>( lhs.getLhs() op rhs ), \
+ lhs.getLhs(), \
+ #op##_sr, \
+ rhs }; \
} \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction< \
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
Detail::is_##id##_0_comparable<LhsT>, \
std::is_same<RhsT, int>>::value, \
BinaryExpr<LhsT, RhsT>> { \
if ( rhs != 0 ) { throw_test_failure_exception(); } \
- return { \
- static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
+ return { static_cast<bool>( lhs.getLhs() op 0 ), \
+ lhs.getLhs(), \
+ #op##_sr, \
+ rhs }; \
} \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
- -> std::enable_if_t< \
+ template <typename LhsT, typename RhsT> \
+ constexpr auto operator op( ExprLhs<LhsT>&& lhs, RhsT rhs ) \
+ ->std::enable_if_t< \
Detail::conjunction< \
Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
Detail::is_##id##_0_comparable<RhsT>, \
std::is_same<LhsT, int>>::value, \
BinaryExpr<LhsT, RhsT>> { \
- if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
- return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
+ if ( lhs.getLhs() != 0 ) { throw_test_failure_exception(); } \
+ return { static_cast<bool>( 0 op rhs ), lhs.getLhs(), #op##_sr, rhs }; \
}
- CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < )
- CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= )
- CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > )
- CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= )
-
- #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR
-
-
-#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op ) \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
- -> std::enable_if_t< \
- !capture_by_value<Detail::RemoveCVRef_t<RhsT>>::value, \
- BinaryExpr<LhsT, RhsT const&>> { \
- return { \
- static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
- } \
- template <typename RhsT> \
- constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
- -> std::enable_if_t<capture_by_value<RhsT>::value, \
- BinaryExpr<LhsT, RhsT>> { \
- return { \
- static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \