Removed special case logic around comparisons between unsigned ints and negative signed ints (as it was non-standard)

This commit is contained in:
Phil Nash 2011-04-01 08:15:08 +01:00
parent 24b352f6b8
commit 751c8bd7f7

View File

@ -48,21 +48,6 @@ namespace Internal
template<> template<>
struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
// Because we capture the LHS and RHS of a binary condition expression by reference, then
// compare the referenced values later, we may get compiler warnings when comparing unsigned
// integer types with integer literals (which are signed - int or long, specifically).
// To avoid this warning we filter out the problem cases as a set of overloads of the compare
// function. In those overloads we cast the unsigned type to its signed equivalent then
// perform the comparison. However we also have to handle the case where the signed value is
// negative. Comparing a negative value with an unsigned value (which will always be positive)
// has fixed logic per operator, so this is captured seperately as an enum value.
enum LostSign
{
None = 0,
LhsSignWasLost = 1,
RhsSignWasLost = 2
};
// So the compare overloads can be operator agnostic we convey the operator as a template // 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. // enum, which is used to specialise an Evaluator for doing the comparison.
template<typename T1, typename T2, Operator Op> template<typename T1, typename T2, Operator Op>
@ -71,87 +56,56 @@ namespace Internal
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsEqualTo> struct Evaluator<T1, T2, IsEqualTo>
{ {
enum{ failsWhen = LhsSignWasLost | RhsSignWasLost };
static bool evaluate( const T1& lhs, const T2& rhs) static bool evaluate( const T1& lhs, const T2& rhs)
{ {
return lhs == rhs; return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsNotEqualTo> struct Evaluator<T1, T2, IsNotEqualTo>
{ {
enum{ failsWhen = None };
static bool evaluate( const T1& lhs, const T2& rhs ) static bool evaluate( const T1& lhs, const T2& rhs )
{ {
return lhs != rhs; return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsLessThan> struct Evaluator<T1, T2, IsLessThan>
{ {
enum{ failsWhen = RhsSignWasLost };
static bool evaluate( const T1& lhs, const T2& rhs ) static bool evaluate( const T1& lhs, const T2& rhs )
{ {
return lhs < rhs; return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsGreaterThan> struct Evaluator<T1, T2, IsGreaterThan>
{ {
enum{ failsWhen = LhsSignWasLost };
static bool evaluate( const T1& lhs, const T2& rhs ) static bool evaluate( const T1& lhs, const T2& rhs )
{ {
return lhs > rhs; return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> struct Evaluator<T1, T2, IsGreaterThanOrEqualTo>
{ {
enum{ failsWhen = LhsSignWasLost };
static bool evaluate( const T1& lhs, const T2& rhs ) static bool evaluate( const T1& lhs, const T2& rhs )
{ {
return lhs >= rhs; return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Evaluator<T1, T2, IsLessThanOrEqualTo> struct Evaluator<T1, T2, IsLessThanOrEqualTo>
{ {
enum{ failsWhen = RhsSignWasLost };
static bool evaluate( const T1& lhs, const T2& rhs ) static bool evaluate( const T1& lhs, const T2& rhs )
{ {
return lhs <= rhs; return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
} }
}; };
// All the special case signed/ unsigned overloads of compare forward to this function,
// which, for negative numbers checks the special case fixed logic, otherwise forwards on
// to the specialised Evaluator for the operator enum
template<Operator Op, typename T1, typename T2> template<Operator Op, typename T1, typename T2>
bool applyEvaluator( const T1& lhs, const T2& rhs, LostSign lostSign ) bool applyEvaluator( const T1& lhs, const T2& rhs )
{ {
typedef Evaluator<T1, T2, Op> EvaluatorType; return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
return lostSign == None
? EvaluatorType::evaluate( lhs, rhs )
: ( EvaluatorType::failsWhen & lostSign ) != lostSign;
}
template<typename T>
LostSign testLhsSign( T lhs )
{
return lhs < 0 ? LhsSignWasLost : None;
}
template<typename T>
LostSign testRhsSign( T rhs )
{
return rhs < 0 ? RhsSignWasLost : None;
} }
// "base" overload // "base" overload
@ -164,57 +118,57 @@ namespace Internal
// unsigned X to int // unsigned X to int
template<Operator Op> bool compare( unsigned int lhs, int rhs ) template<Operator Op> bool compare( unsigned int lhs, int rhs )
{ {
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ), testRhsSign( rhs ) ); return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
} }
template<Operator Op> bool compare( unsigned long lhs, int rhs ) template<Operator Op> bool compare( unsigned long lhs, int rhs )
{ {
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ), testRhsSign( rhs ) ); return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
} }
template<Operator Op> bool compare( unsigned char lhs, int rhs ) template<Operator Op> bool compare( unsigned char lhs, int rhs )
{ {
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ), testRhsSign( rhs ) ); return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
} }
// unsigned X to long // unsigned X to long
template<Operator Op> bool compare( unsigned int lhs, long rhs ) template<Operator Op> bool compare( unsigned int lhs, long rhs )
{ {
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ), testRhsSign( rhs ) ); return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
} }
template<Operator Op> bool compare( unsigned long lhs, long rhs ) template<Operator Op> bool compare( unsigned long lhs, long rhs )
{ {
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ), testRhsSign( rhs ) ); return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
} }
template<Operator Op> bool compare( unsigned char lhs, long rhs ) template<Operator Op> bool compare( unsigned char lhs, long rhs )
{ {
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ), testRhsSign( rhs ) ); return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
} }
// int to unsigned X // int to unsigned X
template<Operator Op> bool compare( int lhs, unsigned int rhs ) template<Operator Op> bool compare( int lhs, unsigned int rhs )
{ {
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs, testLhsSign( lhs ) ); return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
} }
template<Operator Op> bool compare( int lhs, unsigned long rhs ) template<Operator Op> bool compare( int lhs, unsigned long rhs )
{ {
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs, testLhsSign( lhs ) ); return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
} }
template<Operator Op> bool compare( int lhs, unsigned char rhs ) template<Operator Op> bool compare( int lhs, unsigned char rhs )
{ {
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs, testLhsSign( lhs ) ); return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
} }
// long to unsigned X // long to unsigned X
template<Operator Op> bool compare( long lhs, unsigned int rhs ) template<Operator Op> bool compare( long lhs, unsigned int rhs )
{ {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs, testLhsSign( lhs ) ); return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) );
} }
template<Operator Op> bool compare( long lhs, unsigned long rhs ) template<Operator Op> bool compare( long lhs, unsigned long rhs )
{ {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs, testLhsSign( lhs ) ); return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) );
} }
template<Operator Op> bool compare( long lhs, unsigned char rhs ) template<Operator Op> bool compare( long lhs, unsigned char rhs )
{ {
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs, testLhsSign( lhs ) ); return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) );
} }
template<Operator Op, typename T> template<Operator Op, typename T>