/* * Created by Phil on 04/03/2011. * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4389) // '==' : signed/unsigned mismatch #endif #include namespace Catch { namespace Internal { enum Operator { IsEqualTo, IsNotEqualTo, IsLessThan, IsGreaterThan, IsLessThanOrEqualTo, IsGreaterThanOrEqualTo }; template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; template inline T& opCast(T const& t) { return const_cast(t); } // nullptr_t support based on pull request #154 from Konstantin Baumann #ifdef CATCH_CONFIG_CPP11_NULLPTR inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } #endif // CATCH_CONFIG_CPP11_NULLPTR // 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 class Evaluator{}; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs) { return bool( opCast( lhs ) == opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) != opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) < opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) > opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) >= opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) <= opCast( 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 // prevent from overloading ambiguity: SunStudio 11 can't handle function overloads, but can handle class overloads... template struct EvaluatorImpl { bool operator()(T1 const& lhs, T2 const& rhs) { return Evaluator::evaluate( lhs, rhs ); } }; // "base" overload template bool compare( T1 const& lhs, T2 const& rhs ) { return EvaluatorImpl() ( lhs, rhs ); } #undef CATCH_INTERNAL_COMPARE #undef CATCH_INTERNAL_COMPARE_T #define CATCH_INTERNAL_COMPARE( LHS, RHS ) template struct EvaluatorImpl { bool operator()(LHS lhs, RHS rhs) #define CATCH_INTERNAL_COMPARE_T( LHS, RHS ) template struct EvaluatorImpl { bool operator()(LHS lhs, RHS rhs) // unsigned X to int CATCH_INTERNAL_COMPARE( unsigned int , int ) { return applyEvaluator( lhs, static_cast( rhs ) ); }}; CATCH_INTERNAL_COMPARE( unsigned long , int ) { return applyEvaluator( lhs, static_cast( rhs ) ); }}; CATCH_INTERNAL_COMPARE( unsigned char , int ) { return applyEvaluator( lhs, static_cast( rhs ) ); }}; // unsigned X to long CATCH_INTERNAL_COMPARE( unsigned int , long ) { return applyEvaluator( lhs, static_cast( rhs ) ); }}; CATCH_INTERNAL_COMPARE( unsigned long , long ) { return applyEvaluator( lhs, static_cast( rhs ) ); }}; CATCH_INTERNAL_COMPARE( unsigned char , long ) { return applyEvaluator( lhs, static_cast( rhs ) ); }}; // int to unsigned X CATCH_INTERNAL_COMPARE( int , unsigned int ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( int , unsigned long ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( int , unsigned char ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; // long to unsigned X CATCH_INTERNAL_COMPARE( long , unsigned int ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( long , unsigned long ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( long , unsigned char ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; // pointer to long (when comparing against NULL) CATCH_INTERNAL_COMPARE_T( long , T* ) { return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); }}; template bool compare( T* lhs, long rhs ) { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } // pointer to int (when comparing against NULL) CATCH_INTERNAL_COMPARE_T( int , T* ) { return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE_T( T* , int ) { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); }}; #ifdef CATCH_CONFIG_CPP11_LONG_LONG // long long to unsigned X CATCH_INTERNAL_COMPARE( long long , unsigned int ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( long long , unsigned long ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( long long , unsigned long long ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( long long , unsigned char ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; // unsigned long long to X CATCH_INTERNAL_COMPARE( unsigned long long , int ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( unsigned long long , long ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( unsigned long long , long long ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE( unsigned long long , char ) { return applyEvaluator( static_cast( lhs ), rhs ); }}; // pointer to long long (when comparing against NULL) CATCH_INTERNAL_COMPARE_T( long long lhs, T* ) { return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); }}; CATCH_INTERNAL_COMPARE_T( T* , long long ) { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); }}; #endif // CATCH_CONFIG_CPP11_LONG_LONG #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) CATCH_INTERNAL_COMPARE_T( std::nullptr_t, T* ) { return Evaluator::evaluate( nullptr, rhs ); }}; CATCH_INTERNAL_COMPARE_T( T* , std::nullptr_t ) { return Evaluator::evaluate( lhs, nullptr ); }}; #endif // CATCH_CONFIG_CPP11_NULLPTR #undef CATCH_INTERNAL_COMPARE #undef CATCH_INTERNAL_COMPARE_T } // end of namespace Internal } // end of namespace Catch #ifdef _MSC_VER #pragma warning(pop) #endif #endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED