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:
Phil Nash 2013-04-20 23:12:17 +01:00
parent 19279250e8
commit 003960dc90
3 changed files with 44 additions and 53 deletions

View File

@ -11,8 +11,6 @@
// Try to detect if the current compiler supports SFINAE // Try to detect if the current compiler supports SFINAE
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#ifdef CATCH_SFINAE
namespace Catch { namespace Catch {
struct TrueType { struct TrueType {
@ -26,6 +24,8 @@ namespace Catch {
char sizer[2]; char sizer[2];
}; };
#ifdef CATCH_SFINAE
template<bool> struct NotABooleanExpression; template<bool> struct NotABooleanExpression;
template<bool c> struct If : NotABooleanExpression<c> {}; template<bool c> struct If : NotABooleanExpression<c> {};
@ -36,9 +36,9 @@ namespace Catch {
template<> struct SizedIf<sizeof(TrueType)> : TrueType {}; template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
template<> struct SizedIf<sizeof(FalseType)> : FalseType {}; template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
} // end namespace Catch
#endif // CATCH_SFINAE #endif // CATCH_SFINAE
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED

View File

@ -20,11 +20,10 @@
#endif #endif
namespace Catch { namespace Catch {
namespace Detail {
#ifdef CATCH_SFINAE #ifdef CATCH_SFINAE
namespace Detail {
template<typename T> template<typename T>
class IsStreamInsertableHelper { class IsStreamInsertableHelper {
template<int N> struct TrueIfSizeable : TrueType {}; template<int N> struct TrueIfSizeable : TrueType {};
@ -40,53 +39,47 @@ namespace Detail {
template<typename T> template<typename T>
struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {}; 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 #else
namespace Detail { struct BorgType {
template<typename T> BorgType( T const& );
};
struct NonStreamable { TrueType& testStreamable( std::ostream& );
template<typename T> NonStreamable( const T& ){} FalseType testStreamable( FalseType );
FalseType operator<<( std::ostream const&, BorgType const& );
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 } // 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> template<typename T>
struct StringMaker { struct StringMaker :
static std::string convert( T const& value ) { Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
std::ostringstream oss;
oss << value;
return oss.str();
}
};
#endif
template<typename T> template<typename T>

View File

@ -342,11 +342,9 @@ struct Awkward
operator int() const { return 7; } operator int() const { return 7; }
}; };
// This now works with GCC/ Clang usinh SFINAE TEST_CASE( "non streamable - with conv. op", "" )
// Uncomment when it works on all compilers that are tested {
//TEST_CASE( "non streamable", "" ) Awkward awkward;
//{ std::string s = Catch::toString( awkward );
// Awkward awkward; REQUIRE( s == "7" );
// std::string s = Catch::toString( awkward ); }
// REQUIRE( s == "7" ); // This is ambiguous without SFINAE
//}