From 39753558eb635886555a07e0fa01ee72816c06f6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 6 Feb 2017 15:15:43 +0000 Subject: [PATCH] First cut of Evaluate refactoring to remove int specialisations, among other things --- include/internal/catch_assertionresult.h | 22 ++- include/internal/catch_evaluate.hpp | 168 ++++++---------------- include/internal/catch_expression_lhs.hpp | 31 ++-- include/internal/catch_result_builder.h | 2 +- include/internal/catch_result_builder.hpp | 4 +- 5 files changed, 77 insertions(+), 150 deletions(-) diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index e2b979f8..d84cbec3 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -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, ')' ); diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index b2f47cdd..15878c6d 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -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 + template class Evaluator{}; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs) { - return bool( opCast( lhs ) == opCast( rhs ) ); + template<> + struct Evaluator { + template + static bool evaluate( T1& lhs, T2& rhs) { + return static_cast( lhs == rhs ); } }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) != opCast( rhs ) ); + template<> + struct Evaluator { + template + static bool evaluate( T1& lhs, T2& rhs ) { + return bool( lhs != rhs ); } }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) < opCast( rhs ) ); + template<> + struct Evaluator { + template + static bool evaluate( T1& lhs, T2& rhs ) { + return bool( lhs < rhs ); } }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) > opCast( rhs ) ); + template<> + struct Evaluator { + template + static bool evaluate( T1& lhs, T2& rhs ) { + return bool( lhs > rhs ); } }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) >= opCast( rhs ) ); + template<> + struct Evaluator { + template + static bool evaluate( T1& lhs, T2& rhs ) { + return bool( lhs >= rhs ); } }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) <= opCast( rhs ) ); + template<> + struct Evaluator { + template + static bool evaluate( T1& lhs, T2& rhs ) { + return bool( lhs <= rhs ); } }; - template - bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - // This level of indirection allows us to specialise for integer types // to avoid signed/ unsigned warnings // "base" overload template bool compare( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // unsigned X to int - template bool compare( unsigned int lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // unsigned X to long - template bool compare( unsigned int lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // int to unsigned X - template bool compare( int lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // long to unsigned X - template bool compare( long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); + return Evaluator::evaluate( opCast( lhs ), opCast( rhs ) ); } // pointer to long (when comparing against NULL) template bool compare( long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + return Evaluator::evaluate( opCast( reinterpret_cast( lhs ) ), opCast( rhs ) ); } template bool compare( T* lhs, long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + return Evaluator::evaluate( opCast( lhs ), opCast( reinterpret_cast( rhs ) ) ); } // pointer to int (when comparing against NULL) template bool compare( int lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + return Evaluator::evaluate( opCast( reinterpret_cast( lhs ) ), opCast( rhs ) ); } template bool compare( T* lhs, int rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + return Evaluator::evaluate( opCast( lhs ), opCast( reinterpret_cast( rhs ) ) ); } -#ifdef CATCH_CONFIG_CPP11_LONG_LONG - // long long to unsigned X - template bool compare( long long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // unsigned long long to X - template bool compare( unsigned long long lhs, int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long long (when comparing against NULL) - template bool compare( long long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } -#endif // CATCH_CONFIG_CPP11_LONG_LONG - +// Needed? #ifdef CATCH_CONFIG_CPP11_NULLPTR - // pointer to nullptr_t (when comparing against nullptr) - template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( nullptr, rhs ); - } - template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, nullptr ); - } +// // pointer to nullptr_t (when comparing against nullptr) +// template bool compare( std::nullptr_t, T* rhs ) { +// return Evaluator::evaluate( nullptr, rhs ); +// } +// template bool compare( T* lhs, std::nullptr_t ) { +// return Evaluator::evaluate( lhs, nullptr ); +// } #endif // CATCH_CONFIG_CPP11_NULLPTR } // end of namespace Internal diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 9670d2a1..5807aca9 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -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::getName(); - dest += delim; - dest += rhs; + virtual std::string reconstructExpression() const CATCH_OVERRIDE { + return reconstructExpressionImpl + (Catch::toString( m_lhs ), + Catch::toString( m_rhs ), + Internal::OperatorTraits::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: diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index dfdffd5f..3d262159 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -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; diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index 7bb2cdc2..f6da5e85 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -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