Skip to content

Commit

Permalink
Revert "First cut of Evaluate refactoring to remove int specialisatio…
Browse files Browse the repository at this point in the history
…ns, among other things"

This reverts commit 3975355.
  • Loading branch information
philsquared committed Feb 6, 2017
1 parent 2360060 commit 2b74613
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 77 deletions.
22 changes: 2 additions & 20 deletions include/internal/catch_assertionresult.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,7 @@ namespace Catch {
virtual bool isBinaryExpression() const {
return false;
}
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;
}
virtual void reconstructExpression( std::string& dest ) const = 0;

// Only simple binary comparisons can be decomposed.
// If more complex check is required then wrap sub-expressions in parentheses.
Expand Down Expand Up @@ -84,7 +66,7 @@ namespace Catch {

std::string const& reconstructExpression() const {
if( decomposedExpression != CATCH_NULL ) {
reconstructedExpression = decomposedExpression->reconstructExpression();
decomposedExpression->reconstructExpression( reconstructedExpression );
if( parenthesized ) {
reconstructedExpression.insert( 0, 1, '(' );
reconstructedExpression.append( 1, ')' );
Expand Down
168 changes: 124 additions & 44 deletions include/internal/catch_evaluate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,86 +46,166 @@ 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<Operator Op>
template<typename T1, typename T2, Operator Op>
class Evaluator{};

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, IsEqualTo> {
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, IsNotEqualTo> {
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, IsLessThan> {
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, IsGreaterThan> {
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, IsGreaterThanOrEqualTo> {
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<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<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<Op>::evaluate( opCast( lhs ), opCast( 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 );
}

// pointer to long (when comparing against NULL)
template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
return Evaluator<Op>::evaluate( opCast( reinterpret_cast<T*>( lhs ) ), opCast( rhs ) );
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
}
template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
return Evaluator<Op>::evaluate( opCast( lhs ), opCast( reinterpret_cast<T*>( rhs ) ) );
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
}

// pointer to int (when comparing against NULL)
template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
return Evaluator<Op>::evaluate( opCast( reinterpret_cast<T*>( lhs ) ), opCast( rhs ) );
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
}
template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
return Evaluator<Op>::evaluate( opCast( lhs ), opCast( reinterpret_cast<T*>( rhs ) ) );
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
}

// Needed?
#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

#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
Expand Down
31 changes: 21 additions & 10 deletions include/internal/catch_expression_lhs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ class ExpressionLhs : public DecomposedExpression {
.endExpression( *this );
}

virtual std::string reconstructExpression() const CATCH_OVERRIDE {
return Catch::toString( m_truthy );
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
dest = Catch::toString( m_truthy );
}

private:
Expand Down Expand Up @@ -115,11 +115,22 @@ class BinaryExpression : public DecomposedExpression {
return true;
}

virtual std::string reconstructExpression() const CATCH_OVERRIDE {
return reconstructExpressionImpl
(Catch::toString( m_lhs ),
Catch::toString( m_rhs ),
Internal::OperatorTraits<Op>::getName() );
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;
}

private:
Expand All @@ -138,14 +149,14 @@ class MatchExpression : public DecomposedExpression {
return true;
}

virtual std::string reconstructExpression() const CATCH_OVERRIDE {
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
std::string matcherAsString = m_matcher.toString();
std::string dest = Catch::toString( m_arg ) + " ";
dest = Catch::toString( m_arg );
dest += ' ';
if( matcherAsString == Detail::unprintableString )
dest += m_matcherString;
else
dest += matcherAsString;
return dest;
}

private:
Expand Down
2 changes: 1 addition & 1 deletion include/internal/catch_result_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace Catch {

void endExpression( DecomposedExpression const& expr );

virtual std::string reconstructExpression() const CATCH_OVERRIDE;
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;

AssertionResult build() const;
AssertionResult build( DecomposedExpression const& expr ) const;
Expand Down
4 changes: 2 additions & 2 deletions include/internal/catch_result_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ namespace Catch {
return AssertionResult( m_assertionInfo, data );
}

std::string ResultBuilder::reconstructExpression() const {
return m_assertionInfo.capturedExpression;
void ResultBuilder::reconstructExpression( std::string& dest ) const {
dest = m_assertionInfo.capturedExpression;
}

} // end namespace Catch
Expand Down

0 comments on commit 2b74613

Please sign in to comment.