diff --git a/src/libraries/turtle/format.hpp b/src/libraries/turtle/format.hpp index b2e0271..c346712 100644 --- a/src/libraries/turtle/format.hpp +++ b/src/libraries/turtle/format.hpp @@ -62,10 +62,10 @@ namespace detail } template< typename T > - class formatter + class protect { public: - explicit formatter( const T& t ) + explicit protect( const T& t ) : t_( &t ) {} const T& operator*() const @@ -79,74 +79,76 @@ namespace detail private: const T* t_; }; - template< typename T > - formatter< T > format( const T& t ) + std::ostream& operator<<( std::ostream& s, protect< T > t ) { - return formatter< T >( t ); - } - - template< typename T > - BOOST_DEDUCED_TYPENAME boost::disable_if< - detail::is_container< T >, - std::ostream& - >::type - operator<<( std::ostream& s, const formatter< T >& f ) - { - detail::serialize( s, *f ); + format( s, t ); return s; } - inline std::ostream& operator<<( std::ostream& s, const formatter< bool >& f ) + template< typename T > + protect< T > format( const T& t ) { - return s << std::boolalpha << *f; + return protect< T >( t ); } - inline std::ostream& operator<<( std::ostream& s, const formatter< std::string >& f ) + + template< typename T > + void format( std::ostream& s, protect< T > t, + BOOST_DEDUCED_TYPENAME boost::disable_if< + detail::is_container< T > + >::type* = 0 ) { - return s << '"' << *f << '"'; + detail::serialize( s, *t ); } - inline std::ostream& operator<<( std::ostream& s, const formatter< const char* >& f ) + + inline void format( std::ostream& s, protect< bool > b ) { - return s << '"' << *f << '"'; + s << std::boolalpha << *b; + } + inline void format( std::ostream& s, protect< std::string > str ) + { + s << '"' << *str << '"'; + } + inline void format( std::ostream& s, protect< const char* > str ) + { + s << '"' << *str << '"'; } template< typename T1, typename T2 > - std::ostream& operator<<( std::ostream& s, const formatter< std::pair< T1, T2 > >& f ) + void format( std::ostream& s, protect< std::pair< T1, T2 > > p ) { - return s << '(' << mock::format( f->first ) - << ',' << mock::format( f->second ) << ')'; + s << '(' << mock::format( p->first ) + << ',' << mock::format( p->second ) << ')'; } template< typename T > - BOOST_DEDUCED_TYPENAME boost::enable_if< - boost::function_types::is_callable_builtin< T* >, - std::ostream& - >::type - operator<<( std::ostream& s, const formatter< T* >& ) + void format( std::ostream& s, protect< T* >, + BOOST_DEDUCED_TYPENAME boost::enable_if< + boost::function_types::is_callable_builtin< T* > + >::type* = 0 ) { - return s << '?'; + s << '?'; } template< typename T > - BOOST_DEDUCED_TYPENAME boost::enable_if< - detail::is_container< T >, - std::ostream& - >::type - operator<<( std::ostream& s, const formatter< T >& f ) + void format( std::ostream& s, protect< T > c, + BOOST_DEDUCED_TYPENAME boost::enable_if< + detail::is_container< T > + >::type* = 0 ) { s << '('; // if an error is generated by the line below it means T is - // being mismatched for a container because it has a typedef - // const_iterator : the solution would be to add a serialization - // operator for mock::formatter< T >. - for( BOOST_DEDUCED_TYPENAME T::const_iterator it = f->begin(); - it != f->end(); ++it ) + // being mistaken for a container because it has a typedef + // const_iterator : the solution would be to add a format override + // for mock::protect< T >. + for( BOOST_DEDUCED_TYPENAME T::const_iterator it = c->begin(); + it != c->end(); ++it ) { - if( it != f->begin() ) + if( it != c->begin() ) s << ','; s << mock::format( *it ); } - return s << ')'; + s << ')'; } } diff --git a/src/tests/turtle_test/format_test.cpp b/src/tests/turtle_test/format_test.cpp index 391917c..176b2a8 100644 --- a/src/tests/turtle_test/format_test.cpp +++ b/src/tests/turtle_test/format_test.cpp @@ -82,30 +82,30 @@ namespace namespace { - struct formatterable {}; + struct protected_formattable {}; - std::ostream& operator<<( std::ostream& s, const formatterable& ) + std::ostream& operator<<( std::ostream& s, const protected_formattable& ) { BOOST_FAIL( "should not be called" ); return s; } - void format( std::ostream&, const formatterable& ) + void format( std::ostream&, const protected_formattable& ) { BOOST_FAIL( "should not be called" ); } } -BOOST_AUTO_TEST_CASE( formatter_overrides_standard_stream_serialization_and_format_even_if_defined_after_being_used ) +BOOST_AUTO_TEST_CASE( protected_format_overrides_standard_stream_serialization_and_format_even_if_defined_after_being_used ) { - BOOST_CHECK_EQUAL( "formatterable", to_string( formatterable() ) ); + BOOST_CHECK_EQUAL( "protected_formattable", to_string( protected_formattable() ) ); } namespace { - std::ostream& operator<<( std::ostream& s, const mock::formatter< formatterable >& ) + void format( std::ostream& s, mock::protect< protected_formattable > ) { - return s << "formatterable"; + s << "protected_formattable"; } } @@ -205,9 +205,9 @@ namespace }; BOOST_MPL_ASSERT(( mock::detail::is_container< false_positive_container > )); - std::ostream& operator<<( std::ostream& s, const mock::formatter< false_positive_container >& ) + void format( std::ostream& s, mock::protect< false_positive_container > ) { - return s << "false_positive_container"; + s << "false_positive_container"; } }