// Copyright Joakim Karlsson & Kim Gräsman 2010-2012. // 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 IGLOO_STRINGIZE_H #define IGLOO_STRINGIZE_H #include namespace snowhouse { namespace detail { // This type soaks up any implicit conversions and makes the following operator<< // less preferred than any other such operator found via ADL. struct any { // Conversion constructor for any type. template any(T const&); }; // A tag type returned by operator<< for the any struct in this namespace // when T does not support <<. struct tag {}; // Fallback operator<< for types T that don't support <<. tag operator<<(std::ostream&, any const&); // Two overloads to distinguish whether T supports a certain operator expression. // The first overload returns a reference to a two-element character array and is chosen if // T does not support the expression, such as <<, whereas the second overload returns a char // directly and is chosen if T supports the expression. So using sizeof(check()) // returns 2 for the first overload and 1 for the second overload. typedef char yes; typedef char (&no)[2]; no check(tag); template yes check(T const&); template struct is_output_streamable { static const T& x; static const bool value = sizeof(check(std::cout << x)) == sizeof(yes); }; template struct DefaultStringizer { static std::string ToString(const T& value) { std::ostringstream buf; buf << value; return buf.str(); } }; template struct DefaultStringizer { static std::string ToString(const T&) { return "[unsupported type]"; } }; } template struct Stringizer; template std::string Stringize(const T& value) { return Stringizer::ToString(value); } // NOTE: Specialize snowhouse::Stringizer to customize assertion messages template struct Stringizer { static std::string ToString(const T& value) { return detail::DefaultStringizer< T, detail::is_output_streamable::value >::ToString(value); } }; #if __cplusplus > 199711L // We need this because nullptr_t has ambiguous overloads of operator<< in the standard library. template<> struct Stringizer { static std::string ToString(std::nullptr_t) { return "nullptr"; } }; #endif } #endif