1 /* 2 * Created by Phil on 04/03/2011. 3 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 #ifndef TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED 9 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED 10 11 #ifdef _MSC_VER 12 #pragma warning(push) 13 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 14 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 15 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 16 #endif 17 18 #include <cstddef> 19 20 namespace Catch { 21 namespace Internal { 22 23 enum Operator { 24 IsEqualTo, 25 IsNotEqualTo, 26 IsLessThan, 27 IsGreaterThan, 28 IsLessThanOrEqualTo, 29 IsGreaterThanOrEqualTo 30 }; 31 getNameCatch::Internal::OperatorTraits32 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } }; getNameCatch::Internal::OperatorTraits33 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } }; getNameCatch::Internal::OperatorTraits34 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } }; getNameCatch::Internal::OperatorTraits35 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } }; getNameCatch::Internal::OperatorTraits36 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } }; getNameCatch::Internal::OperatorTraits37 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } }; getNameCatch::Internal::OperatorTraits38 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; 39 40 template<typename T> opCast(T const & t)41 T& opCast(T const& t) { return const_cast<T&>(t); } 42 43 // nullptr_t support based on pull request #154 from Konstantin Baumann 44 #ifdef CATCH_CONFIG_CPP11_NULLPTR opCast(std::nullptr_t)45 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } 46 #endif // CATCH_CONFIG_CPP11_NULLPTR 47 48 49 // So the compare overloads can be operator agnostic we convey the operator as a template 50 // enum, which is used to specialise an Evaluator for doing the comparison. 51 template<typename T1, typename T2, Operator Op> 52 struct Evaluator{}; 53 54 template<typename T1, typename T2> 55 struct Evaluator<T1, T2, IsEqualTo> { evaluateCatch::Internal::Evaluator56 static bool evaluate( T1 const& lhs, T2 const& rhs) { 57 return bool( opCast( lhs ) == opCast( rhs ) ); 58 } 59 }; 60 template<typename T1, typename T2> 61 struct Evaluator<T1, T2, IsNotEqualTo> { evaluateCatch::Internal::Evaluator62 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 63 return bool( opCast( lhs ) != opCast( rhs ) ); 64 } 65 }; 66 template<typename T1, typename T2> 67 struct Evaluator<T1, T2, IsLessThan> { evaluateCatch::Internal::Evaluator68 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 69 return bool( opCast( lhs ) < opCast( rhs ) ); 70 } 71 }; 72 template<typename T1, typename T2> 73 struct Evaluator<T1, T2, IsGreaterThan> { evaluateCatch::Internal::Evaluator74 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 75 return bool( opCast( lhs ) > opCast( rhs ) ); 76 } 77 }; 78 template<typename T1, typename T2> 79 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { evaluateCatch::Internal::Evaluator80 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 81 return bool( opCast( lhs ) >= opCast( rhs ) ); 82 } 83 }; 84 template<typename T1, typename T2> 85 struct Evaluator<T1, T2, IsLessThanOrEqualTo> { evaluateCatch::Internal::Evaluator86 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 87 return bool( opCast( lhs ) <= opCast( rhs ) ); 88 } 89 }; 90 91 template<Operator Op, typename T1, typename T2> applyEvaluator(T1 const & lhs,T2 const & rhs)92 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { 93 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); 94 } 95 96 // This level of indirection allows us to specialise for integer types 97 // to avoid signed/ unsigned warnings 98 99 // "base" overload 100 template<Operator Op, typename T1, typename T2> compare(T1 const & lhs,T2 const & rhs)101 bool compare( T1 const& lhs, T2 const& rhs ) { 102 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); 103 } 104 105 // unsigned X to int compare(unsigned int lhs,int rhs)106 template<Operator Op> bool compare( unsigned int lhs, int rhs ) { 107 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); 108 } compare(unsigned long lhs,int rhs)109 template<Operator Op> bool compare( unsigned long lhs, int rhs ) { 110 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); 111 } compare(unsigned char lhs,int rhs)112 template<Operator Op> bool compare( unsigned char lhs, int rhs ) { 113 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); 114 } 115 116 // unsigned X to long compare(unsigned int lhs,long rhs)117 template<Operator Op> bool compare( unsigned int lhs, long rhs ) { 118 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); 119 } compare(unsigned long lhs,long rhs)120 template<Operator Op> bool compare( unsigned long lhs, long rhs ) { 121 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); 122 } compare(unsigned char lhs,long rhs)123 template<Operator Op> bool compare( unsigned char lhs, long rhs ) { 124 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); 125 } 126 127 // int to unsigned X compare(int lhs,unsigned int rhs)128 template<Operator Op> bool compare( int lhs, unsigned int rhs ) { 129 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); 130 } compare(int lhs,unsigned long rhs)131 template<Operator Op> bool compare( int lhs, unsigned long rhs ) { 132 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); 133 } compare(int lhs,unsigned char rhs)134 template<Operator Op> bool compare( int lhs, unsigned char rhs ) { 135 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); 136 } 137 138 // long to unsigned X compare(long lhs,unsigned int rhs)139 template<Operator Op> bool compare( long lhs, unsigned int rhs ) { 140 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 141 } compare(long lhs,unsigned long rhs)142 template<Operator Op> bool compare( long lhs, unsigned long rhs ) { 143 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 144 } compare(long lhs,unsigned char rhs)145 template<Operator Op> bool compare( long lhs, unsigned char rhs ) { 146 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 147 } 148 149 // pointer to long (when comparing against NULL) compare(long lhs,T * rhs)150 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { 151 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); 152 } compare(T * lhs,long rhs)153 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { 154 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); 155 } 156 157 // pointer to int (when comparing against NULL) compare(int lhs,T * rhs)158 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { 159 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); 160 } compare(T * lhs,int rhs)161 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { 162 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); 163 } 164 165 #ifdef CATCH_CONFIG_CPP11_LONG_LONG 166 // long long to unsigned X compare(long long lhs,unsigned int rhs)167 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) { 168 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 169 } compare(long long lhs,unsigned long rhs)170 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) { 171 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 172 } compare(long long lhs,unsigned long long rhs)173 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) { 174 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 175 } compare(long long lhs,unsigned char rhs)176 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) { 177 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 178 } 179 180 // unsigned long long to X compare(unsigned long long lhs,int rhs)181 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) { 182 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 183 } compare(unsigned long long lhs,long rhs)184 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) { 185 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 186 } compare(unsigned long long lhs,long long rhs)187 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) { 188 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 189 } compare(unsigned long long lhs,char rhs)190 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) { 191 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 192 } 193 194 // pointer to long long (when comparing against NULL) compare(long long lhs,T * rhs)195 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) { 196 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); 197 } compare(T * lhs,long long rhs)198 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) { 199 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); 200 } 201 #endif // CATCH_CONFIG_CPP11_LONG_LONG 202 203 #ifdef CATCH_CONFIG_CPP11_NULLPTR 204 // pointer to nullptr_t (when comparing against nullptr) compare(std::nullptr_t,T * rhs)205 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { 206 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); 207 } compare(T * lhs,std::nullptr_t)208 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { 209 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); 210 } 211 #endif // CATCH_CONFIG_CPP11_NULLPTR 212 213 } // end of namespace Internal 214 } // end of namespace Catch 215 216 #ifdef _MSC_VER 217 #pragma warning(pop) 218 #endif 219 220 #endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED 221