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
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,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<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>
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;
oss << value;
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 )
{
std::ostringstream oss;
oss << value;
return oss.str();
return Detail::StringMaker<T, Detail::IsStreamable<T>::value>::apply( value );
}
class TestFailureException

View File

@ -26,6 +26,12 @@ namespace Catch
protected:
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