| /* |
| * 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 |
| #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) |
| #endif |
| |
| #include <cstddef> |
| |
| namespace Catch { |
| namespace Internal { |
| |
| enum Operator { |
| IsEqualTo, |
| IsNotEqualTo, |
| IsLessThan, |
| IsGreaterThan, |
| IsLessThanOrEqualTo, |
| IsGreaterThanOrEqualTo |
| }; |
| |
| const char* operatorName(Operator op); |
| |
| template<typename T> |
| T& opCast(T const& t) { return const_cast<T&>(t); } |
| std::nullptr_t opCast(std::nullptr_t); |
| |
| |
| // 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> |
| struct 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<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<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<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<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<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<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<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); |
| } |
| template<Operator Op, typename T> bool compare( T* lhs, long 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<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); |
| } |
| template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { |
| return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); |
| } |
| |
| // 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 ) ); |
| } |
| |
| // 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 ); |
| } |
| |
| } // end of namespace Internal |
| } // end of namespace Catch |
| |
| #ifdef _MSC_VER |
| #pragma warning(pop) |
| #endif |
| |
| #endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED |