| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #ifndef TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED |
| | #define TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED |
| |
|
| | #include "catch_tostring.h" |
| | #include "catch_stringref.h" |
| | #include "catch_meta.hpp" |
| |
|
| | #include <iosfwd> |
| |
|
| | #ifdef _MSC_VER |
| | #pragma warning(push) |
| | #pragma warning(disable:4389) |
| | #pragma warning(disable:4018) |
| | #pragma warning(disable:4312) |
| | #pragma warning(disable:4180) |
| | #pragma warning(disable:4800) |
| | #endif |
| |
|
| | namespace Catch { |
| |
|
| | struct ITransientExpression { |
| | auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } |
| | auto getResult() const -> bool { return m_result; } |
| | virtual void streamReconstructedExpression( std::ostream &os ) const = 0; |
| |
|
| | ITransientExpression( bool isBinaryExpression, bool result ) |
| | : m_isBinaryExpression( isBinaryExpression ), |
| | m_result( result ) |
| | {} |
| |
|
| | |
| | |
| | virtual ~ITransientExpression(); |
| |
|
| | bool m_isBinaryExpression; |
| | bool m_result; |
| |
|
| | }; |
| |
|
| | void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); |
| |
|
| | template<typename LhsT, typename RhsT> |
| | class BinaryExpr : public ITransientExpression { |
| | LhsT m_lhs; |
| | 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 ) ); |
| | } |
| |
|
| | public: |
| | BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) |
| | : ITransientExpression{ 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"); |
| | } |
| |
|
| | 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 LhsT> |
| | class UnaryExpr : public ITransientExpression { |
| | LhsT m_lhs; |
| |
|
| | void streamReconstructedExpression( std::ostream &os ) const override { |
| | os << Catch::Detail::stringify( m_lhs ); |
| | } |
| |
|
| | public: |
| | explicit UnaryExpr( LhsT lhs ) |
| | : ITransientExpression{ false, static_cast<bool>(lhs) }, |
| | m_lhs( lhs ) |
| | {} |
| | }; |
| |
|
| |
|
| | |
| | template<typename LhsT, typename RhsT> |
| | auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); } |
| | template<typename T> |
| | auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } |
| | template<typename T> |
| | auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); } |
| | template<typename T> |
| | auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } |
| | template<typename T> |
| | auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; } |
| |
|
| | template<typename LhsT, typename RhsT> |
| | auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); } |
| | template<typename T> |
| | auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } |
| | template<typename T> |
| | auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); } |
| | template<typename T> |
| | auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } |
| | template<typename T> |
| | auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; } |
| |
|
| |
|
| | template<typename LhsT> |
| | class ExprLhs { |
| | LhsT m_lhs; |
| | public: |
| | explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} |
| |
|
| | template<typename RhsT> |
| | auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; |
| | } |
| | auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { |
| | return { m_lhs == rhs, m_lhs, "==", rhs }; |
| | } |
| |
|
| | template<typename RhsT> |
| | auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; |
| | } |
| | auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { |
| | return { m_lhs != rhs, m_lhs, "!=", rhs }; |
| | } |
| |
|
| | template<typename RhsT> |
| | auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs }; |
| | } |
| | template<typename RhsT> |
| | auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs }; |
| | } |
| | template<typename RhsT> |
| | auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs }; |
| | } |
| | template<typename RhsT> |
| | auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; |
| | } |
| | template <typename RhsT> |
| | auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs }; |
| | } |
| | template <typename RhsT> |
| | auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs }; |
| | } |
| | template <typename RhsT> |
| | auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const { |
| | return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs }; |
| | } |
| |
|
| | template<typename RhsT> |
| | auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | static_assert(always_false<RhsT>::value, |
| | "operator&& is not supported inside assertions, " |
| | "wrap the expression inside parentheses, or decompose it"); |
| | } |
| |
|
| | template<typename RhsT> |
| | auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { |
| | static_assert(always_false<RhsT>::value, |
| | "operator|| is not supported inside assertions, " |
| | "wrap the expression inside parentheses, or decompose it"); |
| | } |
| |
|
| | auto makeUnaryExpr() const -> UnaryExpr<LhsT> { |
| | return UnaryExpr<LhsT>{ m_lhs }; |
| | } |
| | }; |
| |
|
| | void handleExpression( ITransientExpression const& expr ); |
| |
|
| | template<typename T> |
| | void handleExpression( ExprLhs<T> const& expr ) { |
| | handleExpression( expr.makeUnaryExpr() ); |
| | } |
| |
|
| | struct Decomposer { |
| | template<typename T> |
| | auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { |
| | return ExprLhs<T const&>{ lhs }; |
| | } |
| |
|
| | auto operator <=( bool value ) -> ExprLhs<bool> { |
| | return ExprLhs<bool>{ value }; |
| | } |
| | }; |
| |
|
| | } |
| |
|
| | #ifdef _MSC_VER |
| | #pragma warning(pop) |
| | #endif |
| |
|
| | #endif |
| |
|