mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27: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:
		
							
								
								
									
										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 | ||||
|   | ||||
| @@ -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>"; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash