diff --git a/Test/TrickyTests.cpp b/Test/TrickyTests.cpp index 73378323..707e50d5 100644 --- a/Test/TrickyTests.cpp +++ b/Test/TrickyTests.cpp @@ -41,3 +41,23 @@ TEST_CASE( "succeeding/Tricky/complex lhs", "Where the LHS is not a simple value // This only captures part of the expression, but issues a warning about the rest EXPECT( a == 2 || b == 2 ); } + +struct Opaque +{ + int val; + bool operator ==( const Opaque& o ) + { + return val = o.val; + } +}; + +TEST_CASE( "failing/Tricky/non streamable type", "A failing expression with a non streamable type is still captured" ) +{ + + Opaque o1, o2; + o1.val = 7; + o2.val = 8; + + CHECK( &o1 == &o2 ); + CHECK( o1 == o2 ); +} \ No newline at end of file diff --git a/internal/catch_capture.hpp b/internal/catch_capture.hpp index 060c6cf1..19d1a44d 100644 --- a/internal/catch_capture.hpp +++ b/internal/catch_capture.hpp @@ -18,13 +18,66 @@ namespace Catch { +namespace Detail +{ + // The following code, contributed by Sam Partington, allows us to choose an implementation + // of toString() depending on whether a << overload is available + + struct NonStreamable + { + // allow construction from anything... + template + NonStreamable(Anything) + {} + }; + + // a local operator<< which may be called if there isn't a better one elsewhere... + inline NonStreamable operator << ( std::ostream&, const NonStreamable& ns ) + { + return ns; + } + + template + struct IsStreamable + { + static NoType Deduce( const NonStreamable& ); + static YesType Deduce( std::ostream& ); + + enum + { + value = sizeof( Deduce( Synth() << Synth() ) ) + == sizeof( YesType ) + }; + }; + + // << is available, so use it with ostringstream to make the string + template + struct StringMaker + { + static std::string apply( const T& value ) + { + std::ostringstream oss; + oss << value; + return oss.str(); + } + }; + + // << not available - use a default string + template + struct StringMaker + { + static std::string apply( const T& value ) + { + return "{?}"; + } + }; + +}// end namespace Detail template std::string toString( const T& value ) { - std::ostringstream oss; - oss << value; - return oss.str(); + return Detail::StringMaker::value>::apply( value ); } class TestFailureException diff --git a/internal/catch_common.h b/internal/catch_common.h index d94ca34c..46460853 100644 --- a/internal/catch_common.h +++ b/internal/catch_common.h @@ -26,6 +26,12 @@ namespace Catch protected: NonCopyable(){} }; + + typedef char NoType; + typedef int YesType; + + // create a T for use in sizeof expressions + template T Synth(); } #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED \ No newline at end of file