Contents
operator << overload for
std::ostream
Catch::StringMaker
specialisation
Catch::is_range
specialisation
Exceptions
Enums
Floating
point precision
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
This is the standard way of providing string conversions in C++ - and the chances are you may already provide this for your own purposes. If you’re not familiar with this idiom it involves writing a free function of the form:
std::ostream& operator << ( std::ostream& os, T const& value ) {
<< convertMyTypeToString( value );
os return os;
}
(where T
is your type and
convertMyTypeToString
is where you’ll write whatever code
is necessary to make your type printable - it doesn’t have to be in
another function).
You should put this function in the same namespace as your type, or the global namespace, and have it declared before including Catch’s header.
If you don’t want to provide an operator <<
overload, or you want to convert your type differently for testing
purposes, you can provide a specialization for
Catch::StringMaker<T>
:
namespace Catch {
template<>
struct StringMaker<T> {
static std::string convert( T const& value ) {
return convertMyTypeToString( value );
}
};
}
As a fallback, Catch attempts to detect if the type can be iterated
(begin(T)
and end(T)
are valid) and if it can
be, it is stringified as a range. For certain types this can lead to
infinite recursion, so it can be disabled by specializing
Catch::is_range
like so:
namespace Catch {
template<>
struct is_range<T> {
static const bool value = false;
};
}
By default all exceptions deriving from std::exception
will be translated to strings by calling the what()
method.
For exception types that do not derive from std::exception
- or if what()
does not return a suitable string - use
CATCH_TRANSLATE_EXCEPTION
. This defines a function that
takes your exception type, by reference, and returns a string. It can
appear anywhere in the code - it doesn’t have to be in the same
translation unit. For example:
( MyType const& ex ) {
CATCH_TRANSLATE_EXCEPTIONreturn ex.message();
}
Introduced in Catch2 2.8.0.
Enums that already have a <<
overload for
std::ostream
will convert to strings as expected. If you
only need to convert enums to strings for test reporting purposes you
can provide a StringMaker
specialisations as any other
type. However, as a convenience, Catch provides the
CATCH_REGISTER_ENUM
helper macro that will generate the
StringMaker
specialisation for you with minimal code.
Simply provide it the (qualified) enum name, followed by all the enum
values, and you’re done!
E.g.
enum class Fruits { Banana, Apple, Mango };
( Fruits, Fruits::Banana, Fruits::Apple, Fruits::Mango )
CATCH_REGISTER_ENUM
() {
TEST_CASE( Fruits::Mango == Fruits::Apple );
REQUIRE}
… or if the enum is in a namespace:
namespace Bikeshed {
enum class Colours { Red, Green, Blue };
}
// Important!: This macro must appear at top level scope - not inside a namespace
// You can fully qualify the names, or use a using if you prefer
( Bikeshed::Colours,
CATCH_REGISTER_ENUM::Colours::Red,
Bikeshed::Colours::Green,
Bikeshed::Colours::Blue )
Bikeshed
() {
TEST_CASE( Bikeshed::Colours::Red == Bikeshed::Colours::Blue );
REQUIRE}
Introduced in Catch2 2.8.0.
Catch provides a built-in StringMaker
specialization for
both float
and double
. By default, it uses
what we think is a reasonable precision, but you can customize it by
modifying the precision
static variable inside the
StringMaker
specialization, like so:
::StringMaker<float>::precision = 15;
Catchconst float testFloat1 = 1.12345678901234567899f;
const float testFloat2 = 1.12345678991234567899f;
(testFloat1 == testFloat2); REQUIRE
This assertion will fail and print out the testFloat1
and testFloat2
to 15 decimal places.