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
|
#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
|
#include "catch_sfinae.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -18,6 +20,49 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Catch {
|
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 {
|
namespace Detail {
|
||||||
|
|
||||||
struct NonStreamable {
|
struct NonStreamable {
|
||||||
@ -40,6 +85,10 @@ struct StringMaker {
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct StringMaker<T*> {
|
struct StringMaker<T*> {
|
||||||
static std::string convert( T const* p ) {
|
static std::string convert( T const* p ) {
|
||||||
@ -57,7 +106,7 @@ struct StringMaker<std::vector<T> > {
|
|||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "{ ";
|
oss << "{ ";
|
||||||
for( std::size_t i = 0; i < v.size(); ++ i ) {
|
for( std::size_t i = 0; i < v.size(); ++ i ) {
|
||||||
oss << v[i];
|
oss << toString( v[i] );
|
||||||
if( i < v.size() - 1 )
|
if( i < v.size() - 1 )
|
||||||
oss << ", ";
|
oss << ", ";
|
||||||
}
|
}
|
||||||
@ -83,7 +132,6 @@ namespace Detail {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
std::string toString( const T& value ) {
|
std::string toString( const T& value ) {
|
||||||
return StringMaker<T>::convert( value );
|
return StringMaker<T>::convert( value );
|
||||||
// return Detail::makeString( value );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Built in overloads
|
// Built in overloads
|
||||||
|
@ -182,7 +182,7 @@ namespace ObjectWithConversions
|
|||||||
"Operators at different namespace levels not hijacked by Koenig lookup"
|
"Operators at different namespace levels not hijacked by Koenig lookup"
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Object o;
|
Object o;
|
||||||
REQUIRE(0xc0000000 == o );
|
REQUIRE(0xc0000000 == o );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,14 +337,14 @@ TEST_CASE( "Assertions then sections", "" )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Awkward
|
struct Awkward
|
||||||
{
|
{
|
||||||
operator int() const { return 7; }
|
operator int() const { return 7; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//TEST_CASE( "non streamable", "" )
|
TEST_CASE( "non streamable", "" )
|
||||||
//{
|
{
|
||||||
// Awkward awkward;
|
Awkward awkward;
|
||||||
// std::string s = Catch::toString( awkward );
|
std::string s = Catch::toString( awkward );
|
||||||
// REQUIRE( s == "{?}" );
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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 */,
|
4AEE0326161431070071E950 /* catch_streambuf.h */,
|
||||||
4ACE21C8166CA19700FB5509 /* catch_option.hpp */,
|
4ACE21C8166CA19700FB5509 /* catch_option.hpp */,
|
||||||
2694A1F8169FFF9B004816E3 /* catch_line_wrap.h */,
|
2694A1F8169FFF9B004816E3 /* catch_line_wrap.h */,
|
||||||
|
26759472171C72A400A84BD1 /* catch_sfinae.hpp */,
|
||||||
|
26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */,
|
||||||
);
|
);
|
||||||
name = Infrastructure;
|
name = Infrastructure;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
Loading…
Reference in New Issue
Block a user