mirror of https://github.com/catchorg/Catch2.git
Add opt-in c++11 stream insertable check. (#877)
* Add opt-in c++11 stream insertable check. To opt-in, define CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK. Opt-in fixes #872 and should fix #757 as well.
This commit is contained in:
parent
0354d50278
commit
94425ad59b
|
@ -63,6 +63,7 @@ This can be useful on certain platforms that do not provide ```std::cout``` and
|
||||||
CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr
|
CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr
|
||||||
CATCH_CONFIG_CPP11_SHUFFLE // Use std::shuffle instead of std::random_shuffle
|
CATCH_CONFIG_CPP11_SHUFFLE // Use std::shuffle instead of std::random_shuffle
|
||||||
CATCH_CONFIG_CPP11_TYPE_TRAITS // Use std::enable_if and <type_traits>
|
CATCH_CONFIG_CPP11_TYPE_TRAITS // Use std::enable_if and <type_traits>
|
||||||
|
CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK // Use C++11 expression SFINAE to check if class can be inserted to std::ostream
|
||||||
|
|
||||||
Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative.
|
Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative.
|
||||||
So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support.
|
So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support.
|
||||||
|
@ -70,6 +71,28 @@ You may also suppress any of these features by using the `_NO_` form, e.g. `CATC
|
||||||
|
|
||||||
All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11`
|
All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11`
|
||||||
|
|
||||||
|
## `CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK`
|
||||||
|
|
||||||
|
This flag is off by default, but allows you to resolve problems caused by types with private base class that are streamable, but the classes themselves are not. Without it, the following code will cause a compilation error:
|
||||||
|
```cpp
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include <catch.hpp>
|
||||||
|
struct A {};
|
||||||
|
std::ostream &operator<< (std::ostream &o, const A &v) { return o << 0; }
|
||||||
|
|
||||||
|
struct B : private A {
|
||||||
|
bool operator==(int){ return true;}
|
||||||
|
};
|
||||||
|
|
||||||
|
B f ();
|
||||||
|
std::ostream g ();
|
||||||
|
|
||||||
|
TEST_CASE ("Error in streamable check") {
|
||||||
|
B x;
|
||||||
|
REQUIRE (x == 4);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
# Other toggles
|
# Other toggles
|
||||||
|
|
||||||
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
|
CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases
|
||||||
|
|
|
@ -72,6 +72,7 @@ namespace Detail {
|
||||||
|
|
||||||
extern const std::string unprintableString;
|
extern const std::string unprintableString;
|
||||||
|
|
||||||
|
#if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK)
|
||||||
struct BorgType {
|
struct BorgType {
|
||||||
template<typename T> BorgType( T const& );
|
template<typename T> BorgType( T const& );
|
||||||
};
|
};
|
||||||
|
@ -90,6 +91,20 @@ namespace Detail {
|
||||||
static T const&t;
|
static T const&t;
|
||||||
enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
|
enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
template<typename T>
|
||||||
|
class IsStreamInsertable {
|
||||||
|
template<typename SS, typename TT>
|
||||||
|
static auto test(int)
|
||||||
|
-> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
|
||||||
|
|
||||||
|
template<typename, typename>
|
||||||
|
static auto test(...) -> std::false_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const bool value = decltype(test<std::ostream,const T&>(0))::value;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
|
#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
|
||||||
template<typename T,
|
template<typename T,
|
||||||
|
|
|
@ -51,3 +51,22 @@ TEST_CASE("#833") {
|
||||||
REQUIRE(templated_tests<int>(3));
|
REQUIRE(templated_tests<int>(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test containing example where original stream insertable check breaks compilation
|
||||||
|
#if defined (CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK)
|
||||||
|
namespace {
|
||||||
|
struct A {};
|
||||||
|
std::ostream& operator<< (std::ostream &o, const A &) { return o << 0; }
|
||||||
|
|
||||||
|
struct B : private A {
|
||||||
|
bool operator== (int) const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
B f ();
|
||||||
|
std::ostream g ();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "#872" ) {
|
||||||
|
B x;
|
||||||
|
REQUIRE (x == 4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue