diff --git a/Test/ConditionTests.cpp b/Test/ConditionTests.cpp index 136fe81f..5a2c5751 100644 --- a/Test/ConditionTests.cpp +++ b/Test/ConditionTests.cpp @@ -214,6 +214,19 @@ TEST_CASE( "./failing/conditions/unsigned-negative", "Comparisons between negati CHECK( negative == ui ); } +TEST_CASE( "./succeeding/conditions/ptr", "Pointers can be compared to null" ) +{ + TestData* p = NULL; + TestData* pNULL = NULL; + + REQUIRE( p == NULL ); + REQUIRE( p == pNULL ); + + TestData data; + p = &data; + REQUIRE( p != NULL ); +} + // Not (!) tests // The problem with the ! operator is that it has right-to-left associativity. // This means we can't isolate it when we decompose. The simple REQUIRE( !false ) form, therefore, diff --git a/internal/catch_capture.hpp b/internal/catch_capture.hpp index 0ba08d21..69753f7a 100644 --- a/internal/catch_capture.hpp +++ b/internal/catch_capture.hpp @@ -154,6 +154,39 @@ inline std::string toString { return value ? "true" : "false"; } + +/////////////////////////////////////////////////////////////////////////////// +inline std::string toString +( + void* p +) +{ + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + std::ostringstream oss; + oss << p; + return oss.str(); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline std::string toString +( + T* p +) +{ + return toString( static_cast( p ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +template +inline std::string toString +( + const T* p +) +{ + return toString( static_cast( const_cast( p ) ) ); +} struct TestFailureException { @@ -226,8 +259,9 @@ public: private: friend class ResultBuilder; - template - friend class Expression; + template friend class Expression; + + template friend class PtrExpression; /////////////////////////////////////////////////////////////////////////// MutableResultInfo& captureBoolExpression @@ -361,6 +395,66 @@ private: const T& m_lhs; }; + template + class PtrExpression + { + public: + + /////////////////////////////////////////////////////////////////////////// + PtrExpression + ( + MutableResultInfo& result, + const LhsT* lhs + ) + : m_result( result ), + m_lhs( lhs ) + {} + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator == + ( + const RhsT* rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + // This catches NULL + MutableResultInfo& operator == + ( + LhsT* rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator != + ( + const RhsT* rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + // This catches NULL + MutableResultInfo& operator != + ( + LhsT* rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + private: + MutableResultInfo& m_result; + const LhsT* m_lhs; + }; + class ResultBuilder { public: @@ -389,6 +483,30 @@ public: return expr; } + /////////////////////////////////////////////////////////////////////////// + template + PtrExpression operator->* + ( + const T* operand + ) + { + PtrExpression expr( m_result, operand ); + + return expr; + } + + /////////////////////////////////////////////////////////////////////////// + template + PtrExpression operator->* + ( + T* operand + ) + { + PtrExpression expr( m_result, operand ); + + return expr; + } + /////////////////////////////////////////////////////////////////////////// template ResultBuilder& operator << @@ -478,7 +596,7 @@ class Approx public: /////////////////////////////////////////////////////////////////////////// // !TBD more generic - Approx + explicit Approx ( double d ) diff --git a/internal/catch_common.h b/internal/catch_common.h index 3d010a13..d0181d19 100644 --- a/internal/catch_common.h +++ b/internal/catch_common.h @@ -17,6 +17,9 @@ #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + #ifdef __GNUC__ #define ATTRIBUTE_NORETURN __attribute__ ((noreturn)) #else