mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 21:36:11 +01:00
Added (conditional) SFINAE support.
Better streamable detection for toString using SFINAE (falls back to non-SFINAE version without)
This commit is contained in:
parent
243f2d2caf
commit
5062d3e92b
74
include/internal/catch_compiler_capabilities.h
Normal file
74
include/internal/catch_compiler_capabilities.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Created by Phil on 15/04/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
||||
|
||||
// Much of the following code is based on Boost (1.53)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Borland
|
||||
#ifdef __BORLANDC__
|
||||
|
||||
#if (__BORLANDC__ > 0x582 )
|
||||
#define CATCH_SFINAE
|
||||
#endif
|
||||
|
||||
#endif // __BORLANDC__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EDG
|
||||
#ifdef __EDG_VERSION__
|
||||
|
||||
#if (__EDG_VERSION__ > 238 )
|
||||
#define CATCH_SFINAE
|
||||
#endif
|
||||
|
||||
#endif // __EDG_VERSION__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Digital Mars
|
||||
#ifdef __DMC__
|
||||
|
||||
#if (__DMC__ > 0x840 )
|
||||
#define CATCH_SFINAE
|
||||
#endif
|
||||
|
||||
#endif // __DMC__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GCC
|
||||
#ifdef __GNUC__
|
||||
|
||||
#if __GNUC__ < 3
|
||||
|
||||
#if (__GNUC_MINOR__ >= 96 )
|
||||
#define CATCH_SFINAE
|
||||
#endif
|
||||
|
||||
#elif __GNUC__ >= 3
|
||||
|
||||
#define CATCH_SFINAE
|
||||
|
||||
#endif // __GNUC__ < 3
|
||||
|
||||
|
||||
#endif // __GNUC__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Visual C++
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
|
||||
#define CATCH_SFINAE
|
||||
#endif
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
|
||||
|
44
include/internal/catch_sfinae.hpp
Normal file
44
include/internal/catch_sfinae.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Created by Phil on 15/04/2013.
|
||||
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
|
||||
#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
|
||||
|
||||
// Try to detect if the current compiler supports SFINAE
|
||||
#include "catch_compiler_capabilities.h"
|
||||
|
||||
#ifdef CATCH_SFINAE
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct TrueType {
|
||||
static const bool value = true;
|
||||
typedef void Enable;
|
||||
char sizer[1];
|
||||
};
|
||||
struct FalseType {
|
||||
static const bool value = false;
|
||||
typedef void Disable;
|
||||
char sizer[2];
|
||||
};
|
||||
|
||||
template<bool> struct NotABooleanExpression;
|
||||
|
||||
template<bool c> struct If : NotABooleanExpression<c> {};
|
||||
template<> struct If<true> : TrueType {};
|
||||
template<> struct If<false> : FalseType {};
|
||||
|
||||
template<int size> struct SizedIf;
|
||||
template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
|
||||
template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#endif // CATCH_SFINAE
|
||||
|
||||
#endif // TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
|
||||
|
@ -9,6 +9,8 @@
|
||||
#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
|
||||
|
||||
#include "catch_common.h"
|
||||
#include "catch_sfinae.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
@ -18,6 +20,49 @@
|
||||
#endif
|
||||
|
||||
namespace Catch {
|
||||
|
||||
#ifdef CATCH_SFINAE
|
||||
|
||||
namespace Detail {
|
||||
|
||||
template<typename T>
|
||||
class IsStreamInsertableHelper {
|
||||
template<int N> struct TrueIfSizeable : TrueType {};
|
||||
|
||||
template<typename T2>
|
||||
static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
|
||||
static FalseType dummy(...);
|
||||
|
||||
public:
|
||||
typedef SizedIf<sizeof(dummy((T*)0))> type;
|
||||
};
|
||||
|
||||
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 NonStreamable {
|
||||
@ -40,6 +85,10 @@ struct StringMaker {
|
||||
return oss.str();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct StringMaker<T*> {
|
||||
static std::string convert( T const* p ) {
|
||||
@ -57,7 +106,7 @@ struct StringMaker<std::vector<T> > {
|
||||
std::ostringstream oss;
|
||||
oss << "{ ";
|
||||
for( std::size_t i = 0; i < v.size(); ++ i ) {
|
||||
oss << v[i];
|
||||
oss << toString( v[i] );
|
||||
if( i < v.size() - 1 )
|
||||
oss << ", ";
|
||||
}
|
||||
@ -83,7 +132,6 @@ namespace Detail {
|
||||
template<typename T>
|
||||
std::string toString( const T& value ) {
|
||||
return StringMaker<T>::convert( value );
|
||||
// return Detail::makeString( value );
|
||||
}
|
||||
|
||||
// Built in overloads
|
||||
|
@ -182,7 +182,7 @@ namespace ObjectWithConversions
|
||||
"Operators at different namespace levels not hijacked by Koenig lookup"
|
||||
)
|
||||
{
|
||||
Object o;
|
||||
Object o;
|
||||
REQUIRE(0xc0000000 == o );
|
||||
}
|
||||
}
|
||||
@ -337,14 +337,14 @@ TEST_CASE( "Assertions then sections", "" )
|
||||
}
|
||||
}
|
||||
|
||||
class Awkward
|
||||
struct Awkward
|
||||
{
|
||||
operator int() const { return 7; }
|
||||
};
|
||||
|
||||
//TEST_CASE( "non streamable", "" )
|
||||
//{
|
||||
// Awkward awkward;
|
||||
// std::string s = Catch::toString( awkward );
|
||||
// REQUIRE( s == "{?}" );
|
||||
//}
|
||||
TEST_CASE( "non streamable", "" )
|
||||
{
|
||||
Awkward awkward;
|
||||
std::string s = Catch::toString( awkward );
|
||||
REQUIRE( s == "7" ); // This is ambiguous without SFINAE
|
||||
}
|
||||
|
@ -59,6 +59,8 @@
|
||||
266ECD73170F3C620030D735 /* BDDTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BDDTests.cpp; path = ../../../SelfTest/BDDTests.cpp; sourceTree = "<group>"; };
|
||||
266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_legacy_reporter_adapter.hpp; sourceTree = "<group>"; };
|
||||
266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_legacy_reporter_adapter.h; sourceTree = "<group>"; };
|
||||
26759472171C72A400A84BD1 /* catch_sfinae.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_sfinae.hpp; sourceTree = "<group>"; };
|
||||
26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_compiler_capabilities.h; sourceTree = "<group>"; };
|
||||
26847E5B16BBAB790043B9C1 /* catch_message.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_message.h; sourceTree = "<group>"; };
|
||||
26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = "<group>"; };
|
||||
26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = "<group>"; };
|
||||
@ -395,6 +397,8 @@
|
||||
4AEE0326161431070071E950 /* catch_streambuf.h */,
|
||||
4ACE21C8166CA19700FB5509 /* catch_option.hpp */,
|
||||
2694A1F8169FFF9B004816E3 /* catch_line_wrap.h */,
|
||||
26759472171C72A400A84BD1 /* catch_sfinae.hpp */,
|
||||
26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */,
|
||||
);
|
||||
name = Infrastructure;
|
||||
sourceTree = "<group>";
|
||||
|
Loading…
Reference in New Issue
Block a user