mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	First cut of Evaluate refactoring to remove int specialisations, among other things
This commit is contained in:
		| @@ -21,7 +21,25 @@ namespace Catch { | ||||
|         virtual bool isBinaryExpression() const { | ||||
|             return false; | ||||
|         } | ||||
|         virtual void reconstructExpression( std::string& dest ) const = 0; | ||||
|         virtual std::string reconstructExpression() const = 0; | ||||
|  | ||||
|         std::string reconstructExpressionImpl( std::string const& lhs, std::string const& rhs, std::string const& op ) const { | ||||
|             std::string dest; | ||||
|             char delim = lhs.size() + rhs.size() < 40 && | ||||
|                          lhs.find('\n') == std::string::npos && | ||||
|                          rhs.find('\n') == std::string::npos ? ' ' : '\n'; | ||||
|             dest.reserve( 7 + lhs.size() + rhs.size() ); | ||||
|             // 2 for spaces around operator | ||||
|             // 2 for operator | ||||
|             // 2 for parentheses (conditionally added later) | ||||
|             // 1 for negation (conditionally added later) | ||||
|             dest = lhs; | ||||
|             dest += delim; | ||||
|             dest += op; | ||||
|             dest += delim; | ||||
|             dest += rhs; | ||||
|             return dest; | ||||
|         } | ||||
|  | ||||
|         // Only simple binary comparisons can be decomposed. | ||||
|         // If more complex check is required then wrap sub-expressions in parentheses. | ||||
| @@ -66,7 +84,7 @@ namespace Catch { | ||||
|  | ||||
|         std::string const& reconstructExpression() const { | ||||
|             if( decomposedExpression != CATCH_NULL ) { | ||||
|                 decomposedExpression->reconstructExpression( reconstructedExpression ); | ||||
|                 reconstructedExpression = decomposedExpression->reconstructExpression(); | ||||
|                 if( parenthesized ) { | ||||
|                     reconstructedExpression.insert( 0, 1, '(' ); | ||||
|                     reconstructedExpression.append( 1, ')' ); | ||||
|   | ||||
| @@ -46,166 +46,86 @@ namespace Internal { | ||||
|  | ||||
|     // So the compare overloads can be operator agnostic we convey the operator as a template | ||||
|     // enum, which is used to specialise an Evaluator for doing the comparison. | ||||
|     template<typename T1, typename T2, Operator Op> | ||||
|     template<Operator Op> | ||||
|     class Evaluator{}; | ||||
|  | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsEqualTo> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs) { | ||||
|             return bool( opCast( lhs ) ==  opCast( rhs ) ); | ||||
|     template<> | ||||
|     struct Evaluator<IsEqualTo> { | ||||
|         template<typename T1, typename T2> | ||||
|         static bool evaluate( T1& lhs, T2& rhs) { | ||||
|             return static_cast<bool>( lhs ==  rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsNotEqualTo> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool( opCast( lhs ) != opCast( rhs ) ); | ||||
|     template<> | ||||
|     struct Evaluator<IsNotEqualTo> { | ||||
|         template<typename T1, typename T2> | ||||
|         static bool evaluate( T1& lhs, T2& rhs ) { | ||||
|             return bool( lhs != rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsLessThan> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool( opCast( lhs ) < opCast( rhs ) ); | ||||
|     template<> | ||||
|     struct Evaluator<IsLessThan> { | ||||
|         template<typename T1, typename T2> | ||||
|         static bool evaluate( T1& lhs, T2& rhs ) { | ||||
|             return bool( lhs < rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsGreaterThan> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool( opCast( lhs ) > opCast( rhs ) ); | ||||
|     template<> | ||||
|     struct Evaluator<IsGreaterThan> { | ||||
|         template<typename T1, typename T2> | ||||
|         static bool evaluate( T1& lhs, T2& rhs ) { | ||||
|             return bool( lhs > rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool( opCast( lhs ) >= opCast( rhs ) ); | ||||
|     template<> | ||||
|     struct Evaluator<IsGreaterThanOrEqualTo> { | ||||
|         template<typename T1, typename T2> | ||||
|         static bool evaluate( T1& lhs, T2& rhs ) { | ||||
|             return bool( lhs >= rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsLessThanOrEqualTo> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool( opCast( lhs ) <= opCast( rhs ) ); | ||||
|     template<> | ||||
|     struct Evaluator<IsLessThanOrEqualTo> { | ||||
|         template<typename T1, typename T2> | ||||
|         static bool evaluate( T1& lhs, T2& rhs ) { | ||||
|             return bool( lhs <= rhs ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     template<Operator Op, typename T1, typename T2> | ||||
|     bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { | ||||
|         return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); | ||||
|     } | ||||
|  | ||||
|     // This level of indirection allows us to specialise for integer types | ||||
|     // to avoid signed/ unsigned warnings | ||||
|  | ||||
|     // "base" overload | ||||
|     template<Operator Op, typename T1, typename T2> | ||||
|     bool compare( T1 const& lhs, T2 const& rhs ) { | ||||
|         return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); | ||||
|     } | ||||
|  | ||||
|     // unsigned X to int | ||||
|     template<Operator Op> bool compare( unsigned int lhs, int rhs ) { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned long lhs, int rhs ) { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned char lhs, int rhs ) { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||||
|     } | ||||
|  | ||||
|     // unsigned X to long | ||||
|     template<Operator Op> bool compare( unsigned int lhs, long rhs ) { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned long lhs, long rhs ) { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned char lhs, long rhs ) { | ||||
|         return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||||
|     } | ||||
|  | ||||
|     // int to unsigned X | ||||
|     template<Operator Op> bool compare( int lhs, unsigned int rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( int lhs, unsigned long rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( int lhs, unsigned char rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||||
|     } | ||||
|  | ||||
|     // long to unsigned X | ||||
|     template<Operator Op> bool compare( long lhs, unsigned int rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( long lhs, unsigned long rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( long lhs, unsigned char rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||||
|         return Evaluator<Op>::evaluate( opCast( lhs ), opCast( rhs ) ); | ||||
|     } | ||||
|  | ||||
|     // pointer to long (when comparing against NULL) | ||||
|     template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); | ||||
|         return Evaluator<Op>::evaluate( opCast( reinterpret_cast<T*>( lhs ) ), opCast( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); | ||||
|         return Evaluator<Op>::evaluate( opCast( lhs ), opCast( reinterpret_cast<T*>( rhs ) ) ); | ||||
|     } | ||||
|  | ||||
|     // pointer to int (when comparing against NULL) | ||||
|     template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); | ||||
|         return Evaluator<Op>::evaluate( opCast( reinterpret_cast<T*>( lhs ) ), opCast( rhs ) ); | ||||
|     } | ||||
|     template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); | ||||
|         return Evaluator<Op>::evaluate( opCast( lhs ), opCast( reinterpret_cast<T*>( rhs ) ) ); | ||||
|     } | ||||
|  | ||||
| #ifdef CATCH_CONFIG_CPP11_LONG_LONG | ||||
|     // long long to unsigned X | ||||
|     template<Operator Op> bool compare( long long lhs, unsigned int rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( long long lhs, unsigned long rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( long long lhs, unsigned char rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||||
|     } | ||||
|  | ||||
|     // unsigned long long to X | ||||
|     template<Operator Op> bool compare( unsigned long long lhs, int rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned long long lhs, long rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op> bool compare( unsigned long long lhs, char rhs ) { | ||||
|         return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||||
|     } | ||||
|  | ||||
|     // pointer to long long (when comparing against NULL) | ||||
|     template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); | ||||
|     } | ||||
|     template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); | ||||
|     } | ||||
| #endif // CATCH_CONFIG_CPP11_LONG_LONG | ||||
|  | ||||
| // Needed? | ||||
| #ifdef CATCH_CONFIG_CPP11_NULLPTR | ||||
|     // pointer to nullptr_t (when comparing against nullptr) | ||||
|     template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); | ||||
|     } | ||||
|     template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { | ||||
|         return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); | ||||
|     } | ||||
| //    // pointer to nullptr_t (when comparing against nullptr) | ||||
| //    template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { | ||||
| //        return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); | ||||
| //    } | ||||
| //    template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { | ||||
| //        return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); | ||||
| //    } | ||||
| #endif // CATCH_CONFIG_CPP11_NULLPTR | ||||
|  | ||||
| } // end of namespace Internal | ||||
|   | ||||
| @@ -78,8 +78,8 @@ public: | ||||
|             .endExpression( *this ); | ||||
|     } | ||||
|  | ||||
|     virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { | ||||
|         dest = Catch::toString( m_truthy ); | ||||
|     virtual std::string reconstructExpression() const CATCH_OVERRIDE { | ||||
|         return Catch::toString( m_truthy ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
| @@ -115,22 +115,11 @@ public: | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { | ||||
|         std::string lhs = Catch::toString( m_lhs ); | ||||
|         std::string rhs = Catch::toString( m_rhs ); | ||||
|         char delim = lhs.size() + rhs.size() < 40 && | ||||
|                      lhs.find('\n') == std::string::npos && | ||||
|                      rhs.find('\n') == std::string::npos ? ' ' : '\n'; | ||||
|         dest.reserve( 7 + lhs.size() + rhs.size() ); | ||||
|                    // 2 for spaces around operator | ||||
|                    // 2 for operator | ||||
|                    // 2 for parentheses (conditionally added later) | ||||
|                    // 1 for negation (conditionally added later) | ||||
|         dest = lhs; | ||||
|         dest += delim; | ||||
|         dest += Internal::OperatorTraits<Op>::getName(); | ||||
|         dest += delim; | ||||
|         dest += rhs; | ||||
|     virtual std::string reconstructExpression() const CATCH_OVERRIDE { | ||||
|         return reconstructExpressionImpl | ||||
|                 (Catch::toString( m_lhs ), | ||||
|                  Catch::toString( m_rhs ), | ||||
|                  Internal::OperatorTraits<Op>::getName() ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
| @@ -149,14 +138,14 @@ public: | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { | ||||
|     virtual std::string reconstructExpression() const CATCH_OVERRIDE { | ||||
|         std::string matcherAsString = m_matcher.toString(); | ||||
|         dest = Catch::toString( m_arg ); | ||||
|         dest += ' '; | ||||
|         std::string dest = Catch::toString( m_arg ) + " "; | ||||
|         if( matcherAsString == Detail::unprintableString ) | ||||
|             dest += m_matcherString; | ||||
|         else | ||||
|             dest += matcherAsString; | ||||
|         return dest; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|   | ||||
| @@ -55,7 +55,7 @@ namespace Catch { | ||||
|  | ||||
|         void endExpression( DecomposedExpression const& expr ); | ||||
|  | ||||
|         virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; | ||||
|         virtual std::string reconstructExpression() const CATCH_OVERRIDE; | ||||
|  | ||||
|         AssertionResult build() const; | ||||
|         AssertionResult build( DecomposedExpression const& expr ) const; | ||||
|   | ||||
| @@ -132,8 +132,8 @@ namespace Catch { | ||||
|         return AssertionResult( m_assertionInfo, data ); | ||||
|     } | ||||
|  | ||||
|     void ResultBuilder::reconstructExpression( std::string& dest ) const { | ||||
|         dest = m_assertionInfo.capturedExpression; | ||||
|     std::string ResultBuilder::reconstructExpression() const { | ||||
|         return m_assertionInfo.capturedExpression; | ||||
|     } | ||||
|  | ||||
| } // end namespace Catch | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash