toString() now works with non-specialised non-streamable types

This commit is contained in:
Phil Nash 2010-11-16 19:30:41 +00:00
parent f59ecbcad6
commit 7d1ce5fade
3 changed files with 82 additions and 3 deletions

View File

@ -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 // This only captures part of the expression, but issues a warning about the rest
EXPECT( a == 2 || b == 2 ); 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 );
}

View File

@ -18,14 +18,67 @@
namespace Catch 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<typename Anything>
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<typename T> template<typename T>
std::string toString( const T& value ) struct IsStreamable
{
static NoType Deduce( const NonStreamable& );
static YesType Deduce( std::ostream& );
enum
{
value = sizeof( Deduce( Synth<std::ostream&>() << Synth<const T&>() ) )
== sizeof( YesType )
};
};
// << is available, so use it with ostringstream to make the string
template<typename T, bool streamable>
struct StringMaker
{
static std::string apply( const T& value )
{ {
std::ostringstream oss; std::ostringstream oss;
oss << value; oss << value;
return oss.str(); return oss.str();
} }
};
// << not available - use a default string
template<typename T>
struct StringMaker<T, false>
{
static std::string apply( const T& value )
{
return "{?}";
}
};
}// end namespace Detail
template<typename T>
std::string toString( const T& value )
{
return Detail::StringMaker<T, Detail::IsStreamable<T>::value>::apply( value );
}
class TestFailureException class TestFailureException
{ {

View File

@ -26,6 +26,12 @@ namespace Catch
protected: protected:
NonCopyable(){} NonCopyable(){}
}; };
typedef char NoType;
typedef int YesType;
// create a T for use in sizeof expressions
template<typename T> T Synth();
} }
#endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED