Reworked stringification layer, removed Catch::toString

Now the order of stringification checks is

1) StringMaker specialization
2) operator<<

toString overloads and specializations have been removed.
diff --git a/include/catch.hpp b/include/catch.hpp
index 236ec38..29132e0 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -127,8 +127,8 @@
 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
-#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
-#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
+#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
+#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
 
 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
@@ -194,8 +194,8 @@
 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
-#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
-#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
+#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
+#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
 
 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp
index 6657642..9c974f6 100644
--- a/include/internal/catch_approx.hpp
+++ b/include/internal/catch_approx.hpp
@@ -114,7 +114,7 @@
 
         std::string toString() const {
             std::ostringstream oss;
-            oss << "Approx( " << Catch::toString( m_value ) << " )";
+            oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
             return oss.str();
         }
 
@@ -127,9 +127,11 @@
 }
 
 template<>
-inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
-    return value.toString();
-}
+struct StringMaker<Catch::Detail::Approx> {
+    std::string operator()(Catch::Detail::Approx const& value) {
+        return value.toString();
+    }
+};
 
 } // end namespace Catch
 
diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp
index 756a07f..1ac339b 100644
--- a/include/internal/catch_expression_lhs.hpp
+++ b/include/internal/catch_expression_lhs.hpp
@@ -81,7 +81,7 @@
     }
 
     virtual void reconstructExpression( std::string& dest ) const override {
-        dest = Catch::toString( m_truthy );
+        dest = ::Catch::Detail::stringify( m_truthy );
     }
 
 private:
@@ -120,8 +120,8 @@
     }
 
     virtual void reconstructExpression( std::string& dest ) const override {
-        std::string lhs = Catch::toString( m_lhs );
-        std::string rhs = Catch::toString( m_rhs );
+        std::string lhs = ::Catch::Detail::stringify( m_lhs );
+        std::string rhs = ::Catch::Detail::stringify( m_rhs );
         char delim = lhs.size() + rhs.size() < 40 &&
                      lhs.find('\n') == std::string::npos &&
                      rhs.find('\n') == std::string::npos ? ' ' : '\n';
@@ -155,7 +155,7 @@
 
     virtual void reconstructExpression( std::string& dest ) const override {
         std::string matcherAsString = m_matcher.toString();
-        dest = Catch::toString( m_arg );
+        dest = ::Catch::Detail::stringify( m_arg );
         dest += ' ';
         if( matcherAsString == Detail::unprintableString )
             dest += m_matcherString;
diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h
index 11aee02..e80f7e1 100644
--- a/include/internal/catch_matchers_vector.h
+++ b/include/internal/catch_matchers_vector.h
@@ -25,7 +25,7 @@
             }
 
             virtual std::string describe() const override {
-                return "Contains: " + Catch::toString( m_comparator );
+                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
             }
 
             T const& m_comparator;
@@ -46,7 +46,7 @@
                 return true;
             }
             virtual std::string describe() const override {
-                return "Contains: " + Catch::toString( m_comparator );
+                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
             }
 
             std::vector<T> const& m_comparator;
@@ -70,7 +70,7 @@
                 return true;
             }
             virtual std::string describe() const override {
-                return "Equals: " + Catch::toString( m_comparator );
+                return "Equals: " + ::Catch::Detail::stringify( m_comparator );
             }
             std::vector<T> const& m_comparator;
         };
diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h
index f72eeca..02eb0d6 100644
--- a/include/internal/catch_tostring.h
+++ b/include/internal/catch_tostring.h
@@ -24,226 +24,296 @@
 
 #include <type_traits>
 
+#include <string>
+
+// We need a dummy global operator<< so we can bring it into Catch namespace later
+struct Catch_global_namespace_dummy;
+std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
+
 namespace Catch {
+    // Bring in operator<< from global namespace into Catch namespace
+    using ::operator<<;
 
-// Why we're here.
-template<typename T>
-std::string toString( T const& value );
+    namespace Detail {
+        std::string rawMemoryToString( const void *object, std::size_t size );
 
-// Built in overloads
+        template<typename T>
+        std::string rawMemoryToString( const T& object ) {
+          return rawMemoryToString( &object, sizeof(object) );
+        }
 
-std::string toString( std::string const& value );
-std::string toString( std::wstring const& value );
-std::string toString( const char* const value );
-std::string toString( char* const value );
-std::string toString( const wchar_t* const value );
-std::string toString( wchar_t* const value );
-std::string toString( int value );
-std::string toString( unsigned long value );
-std::string toString( unsigned int value );
-std::string toString( const double value );
-std::string toString( const float value );
-std::string toString( bool value );
-std::string toString( char value );
-std::string toString( signed char value );
-std::string toString( unsigned char value );
+        template<typename T>
+        class IsStreamInsertable {
+            template<typename SS, typename TT>
+            static auto test(int)
+                -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
 
-std::string toString( long long value );
-std::string toString( unsigned long long value );
+            template<typename, typename>
+            static auto test(...)->std::false_type;
 
-std::string toString( std::nullptr_t );
+        public:
+            static const bool value = decltype(test<std::ostream, const T&>(0))::value;
+        };
+    
+    } // namespace Detail
 
-#ifdef __OBJC__
-    std::string toString( NSString const * const& nsstring );
-    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
-    std::string toString( NSObject* const& nsObject );
-#endif
+    // If we decide for C++14, change these to enable_if_ts
+    template <typename T>
+    struct StringMaker {
+        template <typename Fake = T>
+        typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
+            operator()(const Fake& t) {
+            std::stringstream sstr;
+            sstr << t;
+            return sstr.str();
+        }
 
-
-namespace Detail {
-
-    extern const std::string unprintableString;
-
-    template<typename T>
-    class IsStreamInsertable {
-        template<typename SS, typename TT>
-        static auto test(int)
-        -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
-
-        template<typename, typename>
-        static auto test(...) -> std::false_type;
-
-    public:
-        static const bool value = decltype(test<std::ostream,const T&>(0))::value;
-    };
-
-
-    template<typename T,
-             bool IsEnum = std::is_enum<T>::value
-             >
-    struct EnumStringMaker
-    {
-        static std::string convert( T const& ) { return unprintableString; }
-    };
-
-    template<typename T>
-    struct EnumStringMaker<T,true>
-    {
-        static std::string convert( T const& v )
-        {
-            return ::Catch::toString(
-                static_cast<typename std::underlying_type<T>::type>(v)
-                );
+        template <typename Fake = T>
+        typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
+            operator()(const Fake&) {
+            return "{?}";
         }
     };
 
-    template<bool C>
-    struct StringMakerBase {
-        template<typename T>
-        static std::string convert( T const& v )
-        {
-            return EnumStringMaker<T>::convert( v );
+    namespace Detail {
+
+        extern const std::string unprintableString;
+
+        // This function dispatches all stringification requests inside of Catch.
+        // Should be preferably called fully qualified, like ::Catch::Detail::stringify
+        template <typename T>
+        std::string stringify(const T& e) {
+            return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>{}(e);
+        }
+
+    } // namespace Detail
+
+
+    // Some predefined specializations
+
+    template<>
+    struct StringMaker<std::string> {
+        std::string operator()(const std::string& str);
+    };
+    template<>
+    struct StringMaker<std::wstring> {
+        std::string operator()(const std::wstring& wstr);
+    };
+
+    template<>
+    struct StringMaker<char const *> {
+        std::string operator()(char const * str);
+    };
+    template<>
+    struct StringMaker<char *> {
+        std::string operator()(char * str);
+    };
+    template<>
+    struct StringMaker<wchar_t const *> {
+        std::string operator()(wchar_t const * str);
+    };
+    template<>
+    struct StringMaker<wchar_t *> {
+        std::string operator()(wchar_t * str);
+    };
+
+    template<int SZ>
+    struct StringMaker<char[SZ]> {
+        std::string operator()(const char* str) {
+            return ::Catch::Detail::stringify(std::string{ str });
+        }
+    };
+    template<int SZ>
+    struct StringMaker<signed char[SZ]> {
+        std::string operator()(const char* str) {
+            return ::Catch::Detail::stringify(std::string{ str });
+        }
+    };
+    template<int SZ>
+    struct StringMaker<unsigned char[SZ]> {
+        std::string operator()(const char* str) {
+            return ::Catch::Detail::stringify(std::string{ str });
         }
     };
 
     template<>
-    struct StringMakerBase<true> {
-        template<typename T>
-        static std::string convert( T const& _value ) {
+    struct StringMaker<int> {
+        std::string operator()(int value);
+    };
+    template<>
+    struct StringMaker<long> {
+        std::string operator()(long value);
+    };
+    template<>
+    struct StringMaker<long long> {
+        std::string operator()(long long value);
+    };
+    template<>
+    struct StringMaker<unsigned int> {
+        std::string operator()(unsigned int value);
+    };
+    template<>
+    struct StringMaker<unsigned long> {
+        std::string operator()(unsigned long value);
+    };
+    template<>
+    struct StringMaker<unsigned long long> {
+        std::string operator()(unsigned long long value);
+    };
+
+    template<>
+    struct StringMaker<bool> {
+        std::string operator()(bool b);
+    };
+
+    template<>
+    struct StringMaker<char> {
+        std::string operator()(char c);
+    };
+    template<>
+    struct StringMaker<signed char> {
+        std::string operator()(signed char c);
+    };
+    template<>
+    struct StringMaker<unsigned char> {
+        std::string operator()(unsigned char c);
+    };
+
+    template<>
+    struct StringMaker<nullptr_t> {
+        std::string operator()(std::nullptr_t);
+    };
+
+    template<>
+    struct StringMaker<float> {
+        std::string operator()(float value);
+    };
+    template<>
+    struct StringMaker<double> {
+        std::string operator()(double value);
+    };
+
+    template <typename T>
+    struct StringMaker<T*> {
+        template <typename U>
+        std::string operator()(U* p) {
+            if (p) {
+                return ::Catch::Detail::rawMemoryToString(p);
+            } else {
+                return "nullptr";
+            }
+        }
+    };
+
+    template <typename R, typename C>
+    struct StringMaker<R C::*> {
+        std::string operator()(R C::* p) {
+            if (p) {
+                return ::Catch::Detail::rawMemoryToString(p);
+            } else {
+                return "nullptr";
+            }
+        }
+    };
+
+    namespace Detail {
+        template<typename InputIterator>
+        std::string rangeToString(InputIterator first, InputIterator last) {
             std::ostringstream oss;
-            oss << _value;
+            oss << "{ ";
+            if (first != last) {
+                oss << ::Catch::Detail::stringify(*first);
+                for (++first; first != last; ++first)
+                    oss << ", " << ::Catch::Detail::stringify(*first);
+            }
+            oss << " }";
+            return oss.str();
+        }
+    }
+
+    template<typename T, typename Allocator>
+    struct StringMaker<std::vector<T, Allocator> > {
+        std::string operator()( std::vector<T,Allocator> const& v ) {
+            return ::Catch::Detail::rangeToString( v.begin(), v.end() );
+        }
+    };
+
+    // === Pair ===
+    template<typename T1, typename T2>
+    struct StringMaker<std::pair<T1, T2> > {
+        std::string operator()(const std::pair<T1, T2>& pair) {
+            std::ostringstream oss;
+            oss << "{ "
+                << ::Catch::Detail::stringify(pair.first)
+                << ", "
+                << ::Catch::Detail::stringify(pair.second)
+                << " }";
             return oss.str();
         }
     };
 
-    std::string rawMemoryToString( const void *object, std::size_t size );
-
-    template<typename T>
-    inline std::string rawMemoryToString( const T& object ) {
-      return rawMemoryToString( &object, sizeof(object) );
-    }
-
-} // end namespace Detail
-
-template<typename T>
-struct StringMaker :
-    Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
-
-template<typename T>
-struct StringMaker<T*> {
-    template<typename U>
-    static std::string convert( U* p ) {
-        if( !p )
-            return "NULL";
-        else
-            return Detail::rawMemoryToString( p );
-    }
-};
-
-template<typename R, typename C>
-struct StringMaker<R C::*> {
-    static std::string convert( R C::* p ) {
-        if( !p )
-            return "NULL";
-        else
-            return Detail::rawMemoryToString( p );
-    }
-};
-
-namespace Detail {
-    template<typename InputIterator>
-    std::string rangeToString( InputIterator first, InputIterator last );
-}
-
-//template<typename T, typename Allocator>
-//struct StringMaker<std::vector<T, Allocator> > {
-//    static std::string convert( std::vector<T,Allocator> const& v ) {
-//        return Detail::rangeToString( v.begin(), v.end() );
-//    }
-//};
-
-template<typename T, typename Allocator>
-std::string toString( std::vector<T,Allocator> const& v ) {
-    return Detail::rangeToString( v.begin(), v.end() );
-}
-
-
-
-// toString for tuples
-namespace TupleDetail {
-  template<
-      typename Tuple,
-      std::size_t N = 0,
-      bool = (N < std::tuple_size<Tuple>::value)
-      >
-  struct ElementPrinter {
-      static void print( const Tuple& tuple, std::ostream& os )
-      {
-          os << ( N ? ", " : " " )
-             << Catch::toString(std::get<N>(tuple));
-          ElementPrinter<Tuple,N+1>::print(tuple,os);
-      }
-  };
-
-  template<
-      typename Tuple,
-      std::size_t N
-      >
-  struct ElementPrinter<Tuple,N,false> {
-      static void print( const Tuple&, std::ostream& ) {}
-  };
-
-}
-
-template<typename ...Types>
-struct StringMaker<std::tuple<Types...>> {
-
-    static std::string convert( const std::tuple<Types...>& tuple )
-    {
-        std::ostringstream os;
-        os << '{';
-        TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
-        os << " }";
-        return os.str();
-    }
-};
-
-
-namespace Detail {
-    template<typename T>
-    std::string makeString( T const& value ) {
-        return StringMaker<T>::convert( value );
-    }
-} // end namespace Detail
-
-/// \brief converts any type to a string
-///
-/// The default template forwards on to ostringstream - except when an
-/// ostringstream overload does not exist - in which case it attempts to detect
-/// that and writes {?}.
-/// Overload (not specialise) this template for custom typs that you don't want
-/// to provide an ostream overload for.
-template<typename T>
-std::string toString( T const& value ) {
-    return StringMaker<T>::convert( value );
-}
 
 
     namespace Detail {
-    template<typename InputIterator>
-    std::string rangeToString( InputIterator first, InputIterator last ) {
-        std::ostringstream oss;
-        oss << "{ ";
-        if( first != last ) {
-            oss << Catch::toString( *first );
-            for( ++first ; first != last ; ++first )
-                oss << ", " << Catch::toString( *first );
-        }
-        oss << " }";
-        return oss.str();
-    }
-}
+        template<
+            typename Tuple,
+            std::size_t N = 0,
+            bool = (N < std::tuple_size<Tuple>::value)
+            >
+            struct TupleElementPrinter {
+            static void print(const Tuple& tuple, std::ostream& os) {
+                os << (N ? ", " : " ")
+                    << ::Catch::Detail::stringify(std::get<N>(tuple));
+                TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
+            }
+        };
 
-} // end namespace Catch
+        template<
+            typename Tuple,
+            std::size_t N
+        >
+            struct TupleElementPrinter<Tuple, N, false> {
+            static void print(const Tuple&, std::ostream&) {}
+        };
+
+    }
+
+
+    template<typename ...Types>
+    struct StringMaker<std::tuple<Types...>> {
+        std::string operator()(const std::tuple<Types...>& tuple) {
+            std::ostringstream os;
+            os << '{';
+            Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, os);
+            os << " }";
+            return os.str();
+        }
+    };
+
+
+    template<typename T>
+    struct EnumStringMaker {
+        std::string operator()(const T& t) {
+            return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<T>::type>(t));
+        }
+    };
+
+#ifdef __OBJC__
+    template<>
+    struct StringMaker<NSString const *> {
+        std::string operator()(NSString const* const& nsstring);
+    };
+    template<>
+    struct StringMaker<NSString * CATCH_ARC_STRONG> {
+        std::string operator()(NSString * CATCH_ARC_STRONG const& nsstring);
+    };
+    template<>
+    struct StringMaker<NSObject *> {
+        std::string operator()(NSObject* const& nsObject);
+    };
+#endif
+
+
+} // namespace Catch
 
 #endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp
index f20c41a..8fc3c89 100644
--- a/include/internal/catch_tostring.hpp
+++ b/include/internal/catch_tostring.hpp
@@ -35,8 +35,7 @@
         };
     }
 
-    std::string rawMemoryToString( const void *object, std::size_t size )
-    {
+    std::string rawMemoryToString( const void *object, std::size_t size ) {
         // Reverse order for little endian architectures
         int i = 0, end = static_cast<int>( size ), inc = 1;
         if( Endianness::which() == Endianness::Little ) {
@@ -53,70 +52,6 @@
     }
 }
 
-std::string toString( std::string const& value ) {
-    std::string s = value;
-    if( getCurrentContext().getConfig()->showInvisibles() ) {
-        for(size_t i = 0; i < s.size(); ++i ) {
-            std::string subs;
-            switch( s[i] ) {
-            case '\n': subs = "\\n"; break;
-            case '\t': subs = "\\t"; break;
-            default: break;
-            }
-            if( !subs.empty() ) {
-                s = s.substr( 0, i ) + subs + s.substr( i+1 );
-                ++i;
-            }
-        }
-    }
-    return '"' + s + '"';
-}
-std::string toString( std::wstring const& value ) {
-
-    std::string s;
-    s.reserve( value.size() );
-    for(size_t i = 0; i < value.size(); ++i )
-        s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
-    return Catch::toString( s );
-}
-
-std::string toString( const char* const value ) {
-    return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
-}
-
-std::string toString( char* const value ) {
-    return Catch::toString( static_cast<const char*>( value ) );
-}
-
-std::string toString( const wchar_t* const value )
-{
-    return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
-}
-
-std::string toString( wchar_t* const value )
-{
-    return Catch::toString( static_cast<const wchar_t*>( value ) );
-}
-
-std::string toString( int value ) {
-    std::ostringstream oss;
-    oss << value;
-    if( value > Detail::hexThreshold )
-        oss << " (0x" << std::hex << value << ')';
-    return oss.str();
-}
-
-std::string toString( unsigned long value ) {
-    std::ostringstream oss;
-    oss << value;
-    if( value > Detail::hexThreshold )
-        oss << " (0x" << std::hex << value << ')';
-    return oss.str();
-}
-
-std::string toString( unsigned int value ) {
-    return Catch::toString( static_cast<unsigned long>( value ) );
-}
 
 template<typename T>
 std::string fpToString( T value, int precision ) {
@@ -134,74 +69,160 @@
     return d;
 }
 
-std::string toString( const double value ) {
-    return fpToString( value, 10 );
-}
-std::string toString( const float value ) {
-    return fpToString( value, 5 ) + 'f';
+
+//// ======================================================= ////
+//
+//   Out-of-line defs for full specialization of StringMaker
+//
+//// ======================================================= ////
+
+std::string StringMaker<std::string>::operator()(const std::string& str) {
+    if (!getCurrentContext().getConfig()->showInvisibles()) {
+        return '"' + str + '"';
+    }
+
+    std::string s("\"");
+    for (char c : str) {
+        switch (c) {
+        case '\n':
+            s.append("\\n");
+            break;
+        case '\t':
+            s.append("\\t");
+            break;
+        default:
+            s.push_back(c);
+            break;
+        }
+    }
+    s.append("\"");
+    return s;
 }
 
-std::string toString( bool value ) {
-    return value ? "true" : "false";
+std::string StringMaker<std::wstring>::operator()(const std::wstring& wstr) {
+    std::string s;
+    s.reserve(wstr.size());
+    for (auto c : wstr) {
+        s += (c <= 0xff) ? static_cast<char>(c) : '?';
+    }
+    return ::Catch::Detail::stringify(s);
 }
 
-std::string toString( char value ) {
-    if ( value == '\r' )
+std::string StringMaker<char const*>::operator()(char const* str) {
+    if (str) {
+        return ::Catch::Detail::stringify(std::string{ str });
+    } else {
+        return{ "{null string}" };
+    }
+}
+std::string StringMaker<char*>::operator()(char* str) {
+    if (str) {
+        return ::Catch::Detail::stringify(std::string{ str });
+    } else {
+        return{ "{null string}" };
+    }
+}
+std::string StringMaker<wchar_t const*>::operator()(wchar_t const * str) {
+    if (str) {
+        return ::Catch::Detail::stringify(std::wstring{ str });
+    } else {
+        return{ "{null string}" };
+    }
+}
+std::string StringMaker<wchar_t *>::operator()(wchar_t * str) {
+    if (str) {
+        return ::Catch::Detail::stringify(std::wstring{ str });
+    } else {
+        return{ "{null string}" };
+    }
+}
+
+
+std::string StringMaker<int>::operator()(int value) {
+    return ::Catch::Detail::stringify(static_cast<long long>(value));
+}
+std::string StringMaker<long>::operator()(long value) {
+    return ::Catch::Detail::stringify(static_cast<long long>(value));
+}
+std::string StringMaker<long long>::operator()(long long value) {
+    std::ostringstream oss;
+    oss << value;
+    if (value > Detail::hexThreshold) {
+        oss << " (0x" << std::hex << value << ')';
+    }
+    return oss.str();
+}
+
+std::string StringMaker<unsigned int>::operator()(unsigned int value) {
+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
+}
+std::string StringMaker<unsigned long>::operator()(unsigned long value) {
+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
+}
+std::string StringMaker<unsigned long long>::operator()(unsigned long long value) {
+    std::ostringstream oss;
+    oss << value;
+    if (value > Detail::hexThreshold) {
+        oss << " (0x" << std::hex << value << ')';
+    }
+    return oss.str();
+}
+
+
+std::string StringMaker<bool>::operator()(bool b) {
+    return b ? "true" : "false";
+}
+
+std::string StringMaker<char>::operator()(char value) {
+    if (value == '\r') {
         return "'\\r'";
-    if ( value == '\f' )
+    } else if (value == '\f') {
         return "'\\f'";
-    if ( value == '\n' )
+    } else if (value == '\n') {
         return "'\\n'";
-    if ( value == '\t' )
+    } else if (value == '\t') {
         return "'\\t'";
-    if ( '\0' <= value && value < ' ' )
-        return toString( static_cast<unsigned int>( value ) );
-    char chstr[] = "' '";
-    chstr[1] = value;
-    return chstr;
+    } else if ('\0' <= value && value < ' ') {
+        return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
+    } else {
+        char chstr[] = "' '";
+        chstr[1] = value;
+        return chstr;
+    }
+}
+std::string StringMaker<signed char>::operator()(signed char c) {
+    return ::Catch::Detail::stringify(static_cast<char>(c));
+}
+std::string StringMaker<unsigned char>::operator()(unsigned char c) {
+    return ::Catch::Detail::stringify(static_cast<char>(c));
 }
 
-std::string toString( signed char value ) {
-    return toString( static_cast<char>( value ) );
-}
-
-std::string toString( unsigned char value ) {
-    return toString( static_cast<char>( value ) );
-}
-
-std::string toString( long long value ) {
-    std::ostringstream oss;
-    oss << value;
-    if( value > Detail::hexThreshold )
-        oss << " (0x" << std::hex << value << ')';
-    return oss.str();
-}
-std::string toString( unsigned long long value ) {
-    std::ostringstream oss;
-    oss << value;
-    if( value > Detail::hexThreshold )
-        oss << " (0x" << std::hex << value << ')';
-    return oss.str();
-}
-
-std::string toString( std::nullptr_t ) {
+std::string StringMaker<nullptr_t>::operator()(std::nullptr_t) {
     return "nullptr";
 }
 
+std::string StringMaker<float>::operator()(float value) {
+    return fpToString(value, 5) + 'f';
+}
+std::string StringMaker<double>::operator()(double value) {
+    return fpToString(value, 10);
+}
+
+
 #ifdef __OBJC__
-    std::string toString( NSString const * const& nsstring ) {
-        if( !nsstring )
-            return "nil";
-        return "@" + toString([nsstring UTF8String]);
-    }
-    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
-        if( !nsstring )
-            return "nil";
-        return "@" + toString([nsstring UTF8String]);
-    }
-    std::string toString( NSObject* const& nsObject ) {
-        return toString( [nsObject description] );
-    }
+std::string StringMaker<NSString const *>::operator()(NSString const * const& nsstring) {
+    if (!nsstring)
+        return "nil";
+    return "@" + toString([nsstring UTF8String]);
+}
+std::string StringMaker<NSString * CATCH_ARC_STRONG>::operator()(NSString * CATCH_ARC_STRONG const& nsstring) {
+    if (!nsstring)
+        return "nil";
+    return "@" + toString([nsstring UTF8String]);
+}
+std::string StringMaker<NSObject *>::operator()(NSObject * const& nsObject) {
+    return ::Catch::Detail::stringify([nsObject description]);
+}
 #endif
 
 } // end namespace Catch
diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp
index f5cbc47..874b0f9 100644
--- a/include/reporters/catch_reporter_junit.hpp
+++ b/include/reporters/catch_reporter_junit.hpp
@@ -160,7 +160,7 @@
                     xml.writeAttribute( "classname", className );
                     xml.writeAttribute( "name", name );
                 }
-                xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
+                xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
 
                 writeAssertions( sectionNode );
 
diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt
index b62a9a3..9b857c4 100644
--- a/projects/SelfTest/Baselines/console.sw.approved.txt
+++ b/projects/SelfTest/Baselines/console.sw.approved.txt
@@ -119,7 +119,7 @@
 
 MiscTests.cpp:<line number>:
 PASSED:
-  REQUIRE( (*__error()) == 1 )
+  REQUIRE( (*__errno_location ()) == 1 )
 with expansion:
   1 == 1
 
@@ -5873,7 +5873,7 @@
 PASSED:
   REQUIRE( (std::pair<int, int>( 1, 2 )) == aNicePair )
 with expansion:
-  std::pair( 1, 2 ) == std::pair( 1, 2 )
+  { 1, 2 } == { 1, 2 }
 
 -------------------------------------------------------------------------------
 Pointers can be compared to null
@@ -5885,13 +5885,13 @@
 PASSED:
   REQUIRE( p == 0 )
 with expansion:
-  NULL == 0
+  0 == 0
 
 ConditionTests.cpp:<line number>:
 PASSED:
   REQUIRE( p == pNULL )
 with expansion:
-  NULL == NULL
+  0 == 0
 
 ConditionTests.cpp:<line number>:
 PASSED:
@@ -8864,7 +8864,7 @@
 
 ToStringPair.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" )
+  REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" )
 with expansion:
   "{ { 42, "Arthur" }, { "Ford", 24 } }"
   ==
@@ -8880,7 +8880,7 @@
 PASSED:
   REQUIRE( p == 0 )
 with expansion:
-  NULL == 0
+  0 == 0
 
 -------------------------------------------------------------------------------
 random SECTION tests
@@ -9078,7 +9078,7 @@
 
 ToStringPair.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" )
+  REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" )
 with expansion:
   "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
 
@@ -9090,7 +9090,7 @@
 
 ToStringPair.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" )
+  REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" )
 with expansion:
   "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
 
@@ -9102,7 +9102,7 @@
 
 ToStringPair.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" )
+  REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" )
 with expansion:
   "{ { "green", 55 } }"
   ==
@@ -9120,6 +9120,48 @@
   "first" == "second"
 
 -------------------------------------------------------------------------------
+stringify( has_maker )
+-------------------------------------------------------------------------------
+ToStringWhich.cpp:<line number>
+...............................................................................
+
+ToStringWhich.cpp:<line number>:
+PASSED:
+  REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" )
+with expansion:
+  "StringMaker<has_maker>"
+  ==
+  "StringMaker<has_maker>"
+
+-------------------------------------------------------------------------------
+stringify( has_maker_and_toString )
+-------------------------------------------------------------------------------
+ToStringWhich.cpp:<line number>
+...............................................................................
+
+ToStringWhich.cpp:<line number>:
+PASSED:
+  REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" )
+with expansion:
+  "StringMaker<has_maker_and_operator>"
+  ==
+  "StringMaker<has_maker_and_operator>"
+
+-------------------------------------------------------------------------------
+stringify( has_operator )
+-------------------------------------------------------------------------------
+ToStringWhich.cpp:<line number>
+...............................................................................
+
+ToStringWhich.cpp:<line number>:
+PASSED:
+  REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" )
+with expansion:
+  "operator<<( has_operator )"
+  ==
+  "operator<<( has_operator )"
+
+-------------------------------------------------------------------------------
 toString on const wchar_t const pointer returns the string contents
 -------------------------------------------------------------------------------
 MiscTests.cpp:<line number>
@@ -9168,48 +9210,6 @@
   ""wide load"" == ""wide load""
 
 -------------------------------------------------------------------------------
-toString( has_maker )
--------------------------------------------------------------------------------
-ToStringWhich.cpp:<line number>
-...............................................................................
-
-ToStringWhich.cpp:<line number>:
-PASSED:
-  REQUIRE( Catch::toString( item ) == "StringMaker<has_maker>" )
-with expansion:
-  "StringMaker<has_maker>"
-  ==
-  "StringMaker<has_maker>"
-
--------------------------------------------------------------------------------
-toString( has_maker_and_toString )
--------------------------------------------------------------------------------
-ToStringWhich.cpp:<line number>
-...............................................................................
-
-ToStringWhich.cpp:<line number>:
-PASSED:
-  REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" )
-with expansion:
-  "toString( has_maker_and_toString )"
-  ==
-  "toString( has_maker_and_toString )"
-
--------------------------------------------------------------------------------
-toString( has_toString )
--------------------------------------------------------------------------------
-ToStringWhich.cpp:<line number>
-...............................................................................
-
-ToStringWhich.cpp:<line number>:
-PASSED:
-  REQUIRE( Catch::toString( item ) == "toString( has_toString )" )
-with expansion:
-  "toString( has_toString )"
-  ==
-  "toString( has_toString )"
-
--------------------------------------------------------------------------------
 toString( vectors<has_maker )
 -------------------------------------------------------------------------------
 ToStringWhich.cpp:<line number>
@@ -9217,7 +9217,7 @@
 
 ToStringWhich.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker> }" )
+  REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" )
 with expansion:
   "{ StringMaker<has_maker> }"
   ==
@@ -9231,13 +9231,13 @@
 
 EnumToString.cpp:<line number>:
 PASSED:
-  CHECK( Catch::toString(e0) == "E2{0}" )
+  CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" )
 with expansion:
   "E2{0}" == "E2{0}"
 
 EnumToString.cpp:<line number>:
 PASSED:
-  CHECK( Catch::toString(e1) == "E2{1}" )
+  CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" )
 with expansion:
   "E2{1}" == "E2{1}"
 
@@ -9249,13 +9249,13 @@
 
 EnumToString.cpp:<line number>:
 PASSED:
-  CHECK( Catch::toString(e0) == "0" )
+  CHECK( ::Catch::Detail::stringify(e0) == "0" )
 with expansion:
   "0" == "0"
 
 EnumToString.cpp:<line number>:
 PASSED:
-  CHECK( Catch::toString(e1) == "1" )
+  CHECK( ::Catch::Detail::stringify(e1) == "1" )
 with expansion:
   "1" == "1"
 
@@ -9267,19 +9267,19 @@
 
 ToStringVector.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString(vv) == "{  }" )
+  REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
 ToStringVector.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString(vv) == "{ 42 }" )
+  REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" )
 with expansion:
   "{ 42 }" == "{ 42 }"
 
 ToStringVector.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString(vv) == "{ 42, 250 }" )
+  REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" )
 with expansion:
   "{ 42, 250 }" == "{ 42, 250 }"
 
@@ -9291,19 +9291,19 @@
 
 ToStringVector.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString(vv) == "{  }" )
+  REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
 ToStringVector.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString(vv) == "{ \"hello\" }" )
+  REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" )
 with expansion:
   "{ "hello" }" == "{ "hello" }"
 
 ToStringVector.cpp:<line number>:
 PASSED:
-  REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" )
+  REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" )
 with expansion:
   "{ "hello", "world" }"
   ==
diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt
index 6ce6850..f35e745 100644
--- a/projects/SelfTest/Baselines/console.swa4.approved.txt
+++ b/projects/SelfTest/Baselines/console.swa4.approved.txt
@@ -119,7 +119,7 @@
 
 MiscTests.cpp:<line number>:
 PASSED:
-  REQUIRE( (*__error()) == 1 )
+  REQUIRE( (*__errno_location ()) == 1 )
 with expansion:
   1 == 1
 
diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt
index fc9528f..ce6f7d2 100644
--- a/projects/SelfTest/Baselines/junit.sw.approved.txt
+++ b/projects/SelfTest/Baselines/junit.sw.approved.txt
@@ -715,13 +715,13 @@
 TrickyTests.cpp:<line number>
       </failure>
     </testcase>
+    <testcase classname="global" name="stringify( has_maker )" time="{duration}"/>
+    <testcase classname="global" name="stringify( has_maker_and_toString )" time="{duration}"/>
+    <testcase classname="global" name="stringify( has_operator )" time="{duration}"/>
     <testcase classname="global" name="toString on const wchar_t const pointer returns the string contents" time="{duration}"/>
     <testcase classname="global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
     <testcase classname="global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
     <testcase classname="global" name="toString on wchar_t returns the string contents" time="{duration}"/>
-    <testcase classname="global" name="toString( has_maker )" time="{duration}"/>
-    <testcase classname="global" name="toString( has_maker_and_toString )" time="{duration}"/>
-    <testcase classname="global" name="toString( has_toString )" time="{duration}"/>
     <testcase classname="global" name="toString( vectors&lt;has_maker )" time="{duration}"/>
     <testcase classname="global" name="toString(enum w/operator&lt;&lt;)" time="{duration}"/>
     <testcase classname="global" name="toString(enum)" time="{duration}"/>
diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt
index 001ad64..32d233a 100644
--- a/projects/SelfTest/Baselines/xml.sw.approved.txt
+++ b/projects/SelfTest/Baselines/xml.sw.approved.txt
@@ -128,7 +128,7 @@
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/MiscTests.cpp" >
         <Original>
-          (*__error()) == 1
+          (*__errno_location ()) == 1
         </Original>
         <Expanded>
           1 == 1
@@ -6214,7 +6214,7 @@
           (std::pair&lt;int, int>( 1, 2 )) == aNicePair
         </Original>
         <Expanded>
-          std::pair( 1, 2 ) == std::pair( 1, 2 )
+          { 1, 2 } == { 1, 2 }
         </Expanded>
       </Expression>
       <OverallResult success="true"/>
@@ -6225,7 +6225,7 @@
           p == 0
         </Original>
         <Expanded>
-          NULL == 0
+          0 == 0
         </Expanded>
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ConditionTests.cpp" >
@@ -6233,7 +6233,7 @@
           p == pNULL
         </Original>
         <Expanded>
-          NULL == NULL
+          0 == 0
         </Expanded>
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ConditionTests.cpp" >
@@ -9516,7 +9516,7 @@
     <TestCase name="pair&lt;pair&lt;int,const char *,pair&lt;std::string,int> > -> toString" tags="[pair][toString]" filename="projects/<exe-name>/ToStringPair.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringPair.cpp" >
         <Original>
-          Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }"
+          ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }"
         </Original>
         <Expanded>
           "{ { 42, "Arthur" }, { "Ford", 24 } }"
@@ -9532,7 +9532,7 @@
           p == 0
         </Original>
         <Expanded>
-          NULL == 0
+          0 == 0
         </Expanded>
       </Expression>
       <OverallResult success="true"/>
@@ -9743,7 +9743,7 @@
     <TestCase name="std::pair&lt;int,const std::string> -> toString" tags="[pair][toString]" filename="projects/<exe-name>/ToStringPair.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringPair.cpp" >
         <Original>
-          Catch::toString(value) == "{ 34, \"xyzzy\" }"
+          ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }"
         </Original>
         <Expanded>
           "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
@@ -9754,7 +9754,7 @@
     <TestCase name="std::pair&lt;int,std::string> -> toString" tags="[pair][toString]" filename="projects/<exe-name>/ToStringPair.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringPair.cpp" >
         <Original>
-          Catch::toString( value ) == "{ 34, \"xyzzy\" }"
+          ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }"
         </Original>
         <Expanded>
           "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
@@ -9765,7 +9765,7 @@
     <TestCase name="std::vector&lt;std::pair&lt;std::string,int> > -> toString" tags="[pair][toString]" filename="projects/<exe-name>/ToStringPair.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringPair.cpp" >
         <Original>
-          Catch::toString( pr ) == "{ { \"green\", 55 } }"
+          ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }"
         </Original>
         <Expanded>
           "{ { "green", 55 } }"
@@ -9786,6 +9786,45 @@
       </Expression>
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="stringify( has_maker )" tags="[toString]" filename="projects/<exe-name>/ToStringWhich.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringWhich.cpp" >
+        <Original>
+          ::Catch::Detail::stringify( item ) == "StringMaker&lt;has_maker>"
+        </Original>
+        <Expanded>
+          "StringMaker&lt;has_maker>"
+==
+"StringMaker&lt;has_maker>"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="stringify( has_maker_and_toString )" tags="[.][hide][toString]" filename="projects/<exe-name>/ToStringWhich.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringWhich.cpp" >
+        <Original>
+          ::Catch::Detail::stringify( item ) == "StringMaker&lt;has_maker_and_operator>"
+        </Original>
+        <Expanded>
+          "StringMaker&lt;has_maker_and_operator>"
+==
+"StringMaker&lt;has_maker_and_operator>"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="stringify( has_operator )" tags="[toString]" filename="projects/<exe-name>/ToStringWhich.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringWhich.cpp" >
+        <Original>
+          ::Catch::Detail::stringify( item ) == "operator&lt;&lt;( has_operator )"
+        </Original>
+        <Expanded>
+          "operator&lt;&lt;( has_operator )"
+==
+"operator&lt;&lt;( has_operator )"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="toString on const wchar_t const pointer returns the string contents" tags="[toString]" filename="projects/<exe-name>/MiscTests.cpp" >
       <Expression success="true" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
         <Original>
@@ -9830,49 +9869,10 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
-    <TestCase name="toString( has_maker )" description="toString]" filename="projects/<exe-name>/ToStringWhich.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringWhich.cpp" >
-        <Original>
-          Catch::toString( item ) == "StringMaker&lt;has_maker>"
-        </Original>
-        <Expanded>
-          "StringMaker&lt;has_maker>"
-==
-"StringMaker&lt;has_maker>"
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
-    <TestCase name="toString( has_maker_and_toString )" tags="[.][hide][toString]" filename="projects/<exe-name>/ToStringWhich.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringWhich.cpp" >
-        <Original>
-          Catch::toString( item ) == "toString( has_maker_and_toString )"
-        </Original>
-        <Expanded>
-          "toString( has_maker_and_toString )"
-==
-"toString( has_maker_and_toString )"
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
-    <TestCase name="toString( has_toString )" tags="[toString]" filename="projects/<exe-name>/ToStringWhich.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringWhich.cpp" >
-        <Original>
-          Catch::toString( item ) == "toString( has_toString )"
-        </Original>
-        <Expanded>
-          "toString( has_toString )"
-==
-"toString( has_toString )"
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
     <TestCase name="toString( vectors&lt;has_maker )" tags="[toString]" filename="projects/<exe-name>/ToStringWhich.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringWhich.cpp" >
         <Original>
-          Catch::toString( v ) == "{ StringMaker&lt;has_maker> }"
+          ::Catch::Detail::stringify( v ) == "{ StringMaker&lt;has_maker> }"
         </Original>
         <Expanded>
           "{ StringMaker&lt;has_maker> }"
@@ -9885,7 +9885,7 @@
     <TestCase name="toString(enum w/operator&lt;&lt;)" tags="[enum][toString]" filename="projects/<exe-name>/EnumToString.cpp" >
       <Expression success="true" type="CHECK" filename="projects/<exe-name>/EnumToString.cpp" >
         <Original>
-          Catch::toString(e0) == "E2{0}"
+          ::Catch::Detail::stringify(e0) == "E2{0}"
         </Original>
         <Expanded>
           "E2{0}" == "E2{0}"
@@ -9893,7 +9893,7 @@
       </Expression>
       <Expression success="true" type="CHECK" filename="projects/<exe-name>/EnumToString.cpp" >
         <Original>
-          Catch::toString(e1) == "E2{1}"
+          ::Catch::Detail::stringify(e1) == "E2{1}"
         </Original>
         <Expanded>
           "E2{1}" == "E2{1}"
@@ -9904,7 +9904,7 @@
     <TestCase name="toString(enum)" tags="[enum][toString]" filename="projects/<exe-name>/EnumToString.cpp" >
       <Expression success="true" type="CHECK" filename="projects/<exe-name>/EnumToString.cpp" >
         <Original>
-          Catch::toString(e0) == "0"
+          ::Catch::Detail::stringify(e0) == "0"
         </Original>
         <Expanded>
           "0" == "0"
@@ -9912,7 +9912,7 @@
       </Expression>
       <Expression success="true" type="CHECK" filename="projects/<exe-name>/EnumToString.cpp" >
         <Original>
-          Catch::toString(e1) == "1"
+          ::Catch::Detail::stringify(e1) == "1"
         </Original>
         <Expanded>
           "1" == "1"
@@ -9923,7 +9923,7 @@
     <TestCase name="vector&lt;int> -> toString" tags="[toString][vector]" filename="projects/<exe-name>/ToStringVector.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringVector.cpp" >
         <Original>
-          Catch::toString(vv) == "{  }"
+          ::Catch::Detail::stringify(vv) == "{  }"
         </Original>
         <Expanded>
           "{  }" == "{  }"
@@ -9931,7 +9931,7 @@
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringVector.cpp" >
         <Original>
-          Catch::toString(vv) == "{ 42 }"
+          ::Catch::Detail::stringify(vv) == "{ 42 }"
         </Original>
         <Expanded>
           "{ 42 }" == "{ 42 }"
@@ -9939,7 +9939,7 @@
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringVector.cpp" >
         <Original>
-          Catch::toString(vv) == "{ 42, 250 }"
+          ::Catch::Detail::stringify(vv) == "{ 42, 250 }"
         </Original>
         <Expanded>
           "{ 42, 250 }" == "{ 42, 250 }"
@@ -9950,7 +9950,7 @@
     <TestCase name="vector&lt;string> -> toString" tags="[toString][vector]" filename="projects/<exe-name>/ToStringVector.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringVector.cpp" >
         <Original>
-          Catch::toString(vv) == "{  }"
+          ::Catch::Detail::stringify(vv) == "{  }"
         </Original>
         <Expanded>
           "{  }" == "{  }"
@@ -9958,7 +9958,7 @@
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringVector.cpp" >
         <Original>
-          Catch::toString(vv) == "{ \"hello\" }"
+          ::Catch::Detail::stringify(vv) == "{ \"hello\" }"
         </Original>
         <Expanded>
           "{ "hello" }" == "{ "hello" }"
@@ -9966,7 +9966,7 @@
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringVector.cpp" >
         <Original>
-          Catch::toString(vv) == "{ \"hello\", \"world\" }"
+          ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }"
         </Original>
         <Expanded>
           "{ "hello", "world" }"
diff --git a/projects/SelfTest/EnumToString.cpp b/projects/SelfTest/EnumToString.cpp
index 52a3981..eb80c74 100644
--- a/projects/SelfTest/EnumToString.cpp
+++ b/projects/SelfTest/EnumToString.cpp
@@ -1,32 +1,28 @@
 #include "catch.hpp"
 
-/*
-  TODO: maybe ought to check that user-provided specialisations of
- Catch::toString also do the right thing
-*/
 
 // Enum without user-provided stream operator
 enum Enum1 { Enum1Value0, Enum1Value1 };
 
 TEST_CASE( "toString(enum)", "[toString][enum]" ) {
     Enum1 e0 = Enum1Value0;
-    CHECK( Catch::toString(e0) == "0" );
+    CHECK( ::Catch::Detail::stringify(e0) == "0" );
     Enum1 e1 = Enum1Value1;
-    CHECK( Catch::toString(e1) == "1" );
+    CHECK( ::Catch::Detail::stringify(e1) == "1" );
 }
 
 // Enum with user-provided stream operator
 enum Enum2 { Enum2Value0, Enum2Value1 };
 
-inline std::ostream& operator<<( std::ostream& os, Enum2 v ) {
+std::ostream& operator<<( std::ostream& os, Enum2 v ) {
     return os << "E2{" << static_cast<int>(v) << "}";
 }
 
 TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) {
     Enum2 e0 = Enum2Value0;
-    CHECK( Catch::toString(e0) == "E2{0}" );
+    CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" );
     Enum2 e1 = Enum2Value1;
-    CHECK( Catch::toString(e1) == "E2{1}" );
+    CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" );
 }
 
 // Enum class without user-provided stream operator
@@ -34,15 +30,15 @@
 
 TEST_CASE( "toString(enum class)", "[toString][enum][enumClass][c++11][.]" ) {
     EnumClass1 e0 = EnumClass1::EnumClass1Value0;
-    CHECK( Catch::toString(e0) == "0" );
+    CHECK( ::Catch::Detail::stringify(e0) == "0" );
     EnumClass1 e1 = EnumClass1::EnumClass1Value1;
-    CHECK( Catch::toString(e1) == "1" );
+    CHECK( ::Catch::Detail::stringify(e1) == "1" );
 }
 
 // Enum class with user-provided stream operator
 enum class EnumClass2 : short { EnumClass2Value0, EnumClass2Value1 };
 
-inline std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) {
+std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) {
     switch( static_cast<int>( e2 ) ) {
         case static_cast<int>( EnumClass2::EnumClass2Value0 ):
             return os << "E2/V0";
@@ -55,11 +51,11 @@
 
 TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass][c++11][.]" ) {
     EnumClass2 e0 = EnumClass2::EnumClass2Value0;
-    CHECK( Catch::toString(e0) == "E2/V0" );
+    CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" );
     EnumClass2 e1 = EnumClass2::EnumClass2Value1;
-    CHECK( Catch::toString(e1) == "E2/V1" );
+    CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" );
 
     EnumClass2 e3 = static_cast<EnumClass2>(10);
-    CHECK( Catch::toString(e3) == "Unknown enum value 10" );
+    CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" );
 }
 
diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp
index c9754d4..50822de 100644
--- a/projects/SelfTest/ExceptionTests.cpp
+++ b/projects/SelfTest/ExceptionTests.cpp
@@ -144,7 +144,7 @@
 
 CATCH_TRANSLATE_EXCEPTION( double& ex )
 {
-    return Catch::toString( ex );
+    return Catch::Detail::stringify( ex );
 }
 
 TEST_CASE("Non-std exceptions can be translated", "[.][failing][!throws]" )
diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp
index 1c944a3..e097088 100644
--- a/projects/SelfTest/MessageTests.cpp
+++ b/projects/SelfTest/MessageTests.cpp
@@ -134,5 +134,5 @@
 {
     int p;
     WARN( "actual address of p: " << &p );
-    WARN( "toString(p): " << Catch::toString( &p ) );
+    WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) );
 }
diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp
index aab0295..efa5c76 100644
--- a/projects/SelfTest/MiscTests.cpp
+++ b/projects/SelfTest/MiscTests.cpp
@@ -314,25 +314,25 @@
 
 TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) {
         const wchar_t * const s = L"wide load";
-        std::string result = Catch::toString( s );
+        std::string result = ::Catch::Detail::stringify( s );
         CHECK( result == "\"wide load\"" );
 }
 
 TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[toString]" ) {
         const wchar_t * s = L"wide load";
-        std::string result = Catch::toString( s );
+        std::string result = ::Catch::Detail::stringify( s );
         CHECK( result == "\"wide load\"" );
 }
 
 TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) {
         wchar_t * const s = const_cast<wchar_t* const>( L"wide load" );
-        std::string result = Catch::toString( s );
+        std::string result = ::Catch::Detail::stringify( s );
         CHECK( result == "\"wide load\"" );
 }
 
 TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) {
         wchar_t * s = const_cast<wchar_t*>( L"wide load" );
-        std::string result = Catch::toString( s );
+        std::string result = ::Catch::Detail::stringify( s );
         CHECK( result == "\"wide load\"" );
 }
 
diff --git a/projects/SelfTest/ToStringPair.cpp b/projects/SelfTest/ToStringPair.cpp
index 8f51070..38f3085 100644
--- a/projects/SelfTest/ToStringPair.cpp
+++ b/projects/SelfTest/ToStringPair.cpp
@@ -1,37 +1,19 @@
 #include "catch.hpp"
 
-// === Pair ===
-namespace Catch {
-    // Note: If we put this in the right place in catch_tostring, then
-    // we can make it an overload of Catch::toString
-    template<typename T1, typename T2>
-    struct StringMaker<std::pair<T1,T2> > {
-        static std::string convert( const std::pair<T1,T2>& pair ) {
-            std::ostringstream oss;
-            oss << "{ "
-                << toString( pair.first )
-                << ", "
-                << toString( pair.second )
-                << " }";
-            return oss.str();
-        }
-    };
-}
-
 TEST_CASE( "std::pair<int,std::string> -> toString", "[toString][pair]" ) {
     std::pair<int,std::string> value( 34, "xyzzy" );
-    REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" );
+    REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" );
 }
 
 TEST_CASE( "std::pair<int,const std::string> -> toString", "[toString][pair]" ) {
     std::pair<int,const std::string> value( 34, "xyzzy" );
-    REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" );
+    REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" );
 }
 
 TEST_CASE( "std::vector<std::pair<std::string,int> > -> toString", "[toString][pair]" ) {
     std::vector<std::pair<std::string,int> > pr;
     pr.push_back( std::make_pair("green", 55 ) );
-    REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" );
+    REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" );
 }
 
 // This is pretty contrived - I figure if this works, anything will...
@@ -43,5 +25,5 @@
     right_t right( "Ford", 24 );
 
     std::pair<left_t,right_t> pair( left, right );
-    REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" );
+    REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" );
 }
diff --git a/projects/SelfTest/ToStringTuple.cpp b/projects/SelfTest/ToStringTuple.cpp
index 9c85571..dcd1d80 100644
--- a/projects/SelfTest/ToStringTuple.cpp
+++ b/projects/SelfTest/ToStringTuple.cpp
@@ -5,42 +5,42 @@
 TEST_CASE( "tuple<>", "[toString][tuple][c++11][.]" )
 {
     typedef std::tuple<> type;
-    CHECK( "{ }" == Catch::toString(type{}) );
+    CHECK( "{ }" == ::Catch::Detail::stringify(type{}) );
     type value {};
-    CHECK( "{ }" == Catch::toString(value) );
+    CHECK( "{ }" == ::Catch::Detail::stringify(value) );
 }
 
 TEST_CASE( "tuple<int>", "[toString][tuple][c++11][.]" )
 {
     typedef std::tuple<int> type;
-    CHECK( "{ 0 }" == Catch::toString(type{0}) );
+    CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) );
 }
 
 
 TEST_CASE( "tuple<float,int>", "[toString][tuple][c++11][.]" )
 {
     typedef std::tuple<float,int> type;
-    CHECK( "1.2f" == Catch::toString(float(1.2)) );
-    CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2f,0}) );
+    CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) );
+    CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) );
 }
 
 TEST_CASE( "tuple<string,string>", "[toString][tuple][c++11][.]" )
 {
     typedef std::tuple<std::string,std::string> type;
-    CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) );
+    CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) );
 }
 
 TEST_CASE( "tuple<tuple<int>,tuple<>,float>", "[toString][tuple][c++11][.]" )
 {
     typedef std::tuple<std::tuple<int>,std::tuple<>,float> type;
     type value { std::tuple<int>{42}, {}, 1.2f };
-    CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) );
+    CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) );
 }
 
 TEST_CASE( "tuple<nullptr,int,const char *>", "[toString][tuple][c++11][.]" )
 {
     typedef std::tuple<std::nullptr_t,int,const char *> type;
     type value { nullptr, 42, "Catch me" };
-    CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) );
+    CHECK( "{ nullptr, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) );
 }
 
diff --git a/projects/SelfTest/ToStringVector.cpp b/projects/SelfTest/ToStringVector.cpp
index eafe886..c70872c 100644
--- a/projects/SelfTest/ToStringVector.cpp
+++ b/projects/SelfTest/ToStringVector.cpp
@@ -6,21 +6,21 @@
 TEST_CASE( "vector<int> -> toString", "[toString][vector]" )
 {
     std::vector<int> vv;
-    REQUIRE( Catch::toString(vv) == "{  }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" );
     vv.push_back( 42 );
-    REQUIRE( Catch::toString(vv) == "{ 42 }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" );
     vv.push_back( 250 );
-    REQUIRE( Catch::toString(vv) == "{ 42, 250 }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" );
 }
 
 TEST_CASE( "vector<string> -> toString", "[toString][vector]" )
 {
     std::vector<std::string> vv;
-    REQUIRE( Catch::toString(vv) == "{  }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" );
     vv.push_back( "hello" );
-    REQUIRE( Catch::toString(vv) == "{ \"hello\" }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" );
     vv.push_back( "world" );
-    REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" );
 }
 
 namespace {
@@ -50,19 +50,19 @@
 
 TEST_CASE( "vector<int,allocator> -> toString", "[toString][vector,allocator][c++11][.]" ) {
     std::vector<int,minimal_allocator<int> > vv;
-    REQUIRE( Catch::toString(vv) == "{  }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" );
     vv.push_back( 42 );
-    REQUIRE( Catch::toString(vv) == "{ 42 }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" );
     vv.push_back( 250 );
-    REQUIRE( Catch::toString(vv) == "{ 42, 250 }" );
+    REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" );
 }
 
 TEST_CASE( "vec<vec<string,alloc>> -> toString", "[toString][vector,allocator][c++11][.]" ) {
     using inner = std::vector<std::string, minimal_allocator<std::string>>;
     using vector = std::vector<inner>;
     vector v;
-    REQUIRE( Catch::toString(v) == "{  }" );
+    REQUIRE( ::Catch::Detail::stringify(v) == "{  }" );
     v.push_back( inner { "hello" } );
     v.push_back( inner { "world" } );
-    REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" );
+    REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" );
 }
diff --git a/projects/SelfTest/ToStringWhich.cpp b/projects/SelfTest/ToStringWhich.cpp
index a1d2a60..8bd1b6f 100644
--- a/projects/SelfTest/ToStringWhich.cpp
+++ b/projects/SelfTest/ToStringWhich.cpp
@@ -5,67 +5,69 @@
 */
 
 
-struct has_toString { };
+struct has_operator { };
 struct has_maker {};
-struct has_maker_and_toString {};
+struct has_maker_and_operator {};
+
+std::ostream& operator<<(std::ostream& os, const has_operator&) {
+    os << "operator<<( has_operator )";
+    return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const has_maker_and_operator&) {
+    os << "operator<<( has_maker_and_operator )";
+    return os;
+}
 
 namespace Catch {
-    inline std::string toString( const has_toString& ) {
-        return "toString( has_toString )";
-    }
-    inline std::string toString( const has_maker_and_toString& ) {
-        return "toString( has_maker_and_toString )";
-    }
     template<>
     struct StringMaker<has_maker> {
-        static std::string convert( const has_maker& ) {
+        std::string operator()( const has_maker& ) {
             return "StringMaker<has_maker>";
         }
     };
     template<>
-    struct StringMaker<has_maker_and_toString> {
-        static std::string convert( const has_maker_and_toString& ) {
-            return "StringMaker<has_maker_and_toString>";
+    struct StringMaker<has_maker_and_operator> {
+        std::string operator()( const has_maker_and_operator& ) {
+            return "StringMaker<has_maker_and_operator>";
         }
     };
 }
 
-// Call the overload
-TEST_CASE( "toString( has_toString )", "[toString]" ) {
-    has_toString item;
-    REQUIRE( Catch::toString( item ) == "toString( has_toString )" );
+// Call the operator
+TEST_CASE( "stringify( has_operator )", "[toString]" ) {
+    has_operator item;
+    REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" );
 }
 
-// Call the overload
-TEST_CASE( "toString( has_maker )", "toString]" ) {
+// Call the stringmaker
+TEST_CASE( "stringify( has_maker )", "[toString]" ) {
     has_maker item;
-    REQUIRE( Catch::toString( item ) == "StringMaker<has_maker>" );
+    REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" );
 }
 
-// Call the overload
-TEST_CASE( "toString( has_maker_and_toString )", "[.][toString]" ) {
-    has_maker_and_toString item;
-    REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" );
+// Call the stringmaker
+TEST_CASE( "stringify( has_maker_and_toString )", "[.][toString]" ) {
+    has_maker_and_operator item;
+    REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" );
 }
 
 // Vectors...
 
 // Don't run this in approval tests as it is sensitive to two phase lookup differences
 TEST_CASE( "toString( vectors<has_toString )", "[.][toString][!nonportable]" ) {
-    std::vector<has_toString> v(1);
-    // This invokes template<T> toString which actually gives us '{ ? }'
-    REQUIRE( Catch::toString( v ) == "{ {?} }" );
+    std::vector<has_operator> v(1);
+    REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" );
 }
 
 TEST_CASE( "toString( vectors<has_maker )", "[toString]" ) {
     std::vector<has_maker> v(1);
-    REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker> }" );
+    REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" );
 }
 
 
 // Don't run this in approval tests as it is sensitive to two phase lookup differences
 TEST_CASE( "toString( vectors<has_maker_and_toString )", "[.][toString][!nonportable]" ) {
-    std::vector<has_maker_and_toString> v(1);
-    // Note: This invokes the template<T> toString -> StringMaker
-    REQUIRE( Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" );
+    std::vector<has_maker_and_operator> v(1);
+    REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_toString> }" );
 }
diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp
index 129fc2a..e5616d0 100644
--- a/projects/SelfTest/TrickyTests.cpp
+++ b/projects/SelfTest/TrickyTests.cpp
@@ -14,15 +14,11 @@
 
 #include "catch.hpp"
 
-namespace Catch
-{
-    template<>
-    std::string toString<std::pair<int, int> >( const std::pair<int, int>& value )
-    {
+namespace Catch {
+    std::string toString( const std::pair<int, int>& value ) {
         std::ostringstream oss;
         oss << "std::pair( " << value.first << ", " << value.second << " )";
         return oss.str();
-
     }
 }
 
@@ -340,7 +336,7 @@
 TEST_CASE( "non streamable - with conv. op", "[Tricky]" )
 {
     Awkward awkward;
-    std::string s = Catch::toString( awkward );
+    std::string s = ::Catch::Detail::stringify( awkward );
     REQUIRE( s == "7" );
 }