mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Returned to older version of IsStreamable
- this time based on code from Martin Moene https://gist.github.com/martinmoene/5418947#file-insertionopdetector-cpp
This commit is contained in:
		| @@ -11,8 +11,6 @@ | ||||
| // Try to detect if the current compiler supports SFINAE | ||||
| #include "catch_compiler_capabilities.h" | ||||
|  | ||||
| #ifdef CATCH_SFINAE | ||||
|  | ||||
| namespace Catch { | ||||
|      | ||||
|     struct TrueType { | ||||
| @@ -26,6 +24,8 @@ namespace Catch { | ||||
|         char sizer[2]; | ||||
|     }; | ||||
|  | ||||
| #ifdef CATCH_SFINAE | ||||
|  | ||||
|     template<bool> struct NotABooleanExpression; | ||||
|  | ||||
|     template<bool c> struct If : NotABooleanExpression<c> {}; | ||||
| @@ -35,10 +35,10 @@ namespace Catch { | ||||
|     template<int size> struct SizedIf; | ||||
|     template<> struct SizedIf<sizeof(TrueType)> : TrueType {}; | ||||
|     template<> struct SizedIf<sizeof(FalseType)> : FalseType {}; | ||||
|  | ||||
| #endif // CATCH_SFINAE | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // CATCH_SFINAE | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED | ||||
|  | ||||
|   | ||||
| @@ -20,11 +20,10 @@ | ||||
| #endif | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Detail { | ||||
|  | ||||
| #ifdef CATCH_SFINAE | ||||
|  | ||||
| namespace Detail { | ||||
|  | ||||
|     template<typename T> | ||||
|     class IsStreamInsertableHelper { | ||||
|         template<int N> struct TrueIfSizeable : TrueType {}; | ||||
| @@ -40,53 +39,47 @@ namespace Detail { | ||||
|     template<typename T> | ||||
|     struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {}; | ||||
|  | ||||
|     template<typename T> | ||||
|     void toStream( std::ostream& os, T const& value, typename IsStreamInsertable<T>::Enable* = 0 ) { | ||||
|         os << value; | ||||
|     } | ||||
|  | ||||
|     template<typename T> | ||||
|     void toStream( std::ostream& os, T const&, typename IsStreamInsertable<T>::Disable* = 0 ) { | ||||
|         os << "{?}"; | ||||
|     } | ||||
|     | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| struct StringMaker { | ||||
|     static std::string convert( T const& value ) { | ||||
|         std::ostringstream oss; | ||||
|         Detail::toStream( oss, value ); | ||||
|         return oss.str(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #else | ||||
|  | ||||
| namespace Detail { | ||||
|     struct BorgType { | ||||
|         template<typename T> BorgType( T const& ); | ||||
|     }; | ||||
|    | ||||
|     TrueType& testStreamable( std::ostream& ); | ||||
|     FalseType testStreamable( FalseType ); | ||||
|      | ||||
|     FalseType operator<<( std::ostream const&, BorgType const& ); | ||||
|  | ||||
|     struct NonStreamable { | ||||
|         template<typename T> NonStreamable( const T& ){} | ||||
|     template<typename T> | ||||
|     struct IsStreamInsertable { | ||||
|         static std::ostream &s; | ||||
|         static T const &t; | ||||
|         enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; | ||||
|     }; | ||||
|      | ||||
| #endif | ||||
|  | ||||
|     template<bool C> | ||||
|     struct StringMakerBase { | ||||
|         template<typename T> | ||||
|         static std::string convert( T const& ) { return "{?}"; } | ||||
|     }; | ||||
|  | ||||
|     template<> | ||||
|     struct StringMakerBase<true> { | ||||
|         template<typename T> | ||||
|         static std::string convert( T const& _value ) { | ||||
|             std::ostringstream oss; | ||||
|             oss << _value; | ||||
|             return oss.str(); | ||||
|         } | ||||
|     }; | ||||
|      | ||||
| } // end namespace Detail | ||||
|  | ||||
| // If the type does not have its own << overload for ostream then | ||||
| // this one will be used instead | ||||
| inline std::ostream& operator << ( std::ostream& ss, Detail::NonStreamable ){ | ||||
|     return ss << "{?}"; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| struct StringMaker { | ||||
|     static std::string convert( T const& value ) { | ||||
|         std::ostringstream oss; | ||||
|         oss << value; | ||||
|         return oss.str(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| struct StringMaker : | ||||
|     Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; | ||||
|  | ||||
|  | ||||
| template<typename T> | ||||
|   | ||||
| @@ -342,11 +342,9 @@ struct Awkward | ||||
|     operator int() const { return 7; } | ||||
| }; | ||||
|  | ||||
| // This now works with GCC/ Clang usinh SFINAE | ||||
| // Uncomment when it works on all compilers that are tested | ||||
| //TEST_CASE( "non streamable", "" ) | ||||
| //{ | ||||
| //    Awkward awkward; | ||||
| //    std::string s = Catch::toString( awkward ); | ||||
| //    REQUIRE( s == "7" ); // This is ambiguous without SFINAE | ||||
| //} | ||||
| TEST_CASE( "non streamable - with conv. op", "" ) | ||||
| { | ||||
|     Awkward awkward; | ||||
|     std::string s = Catch::toString( awkward ); | ||||
|     REQUIRE( s == "7" ); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash