diff --git a/include/boost/exception/detail/is_output_streamable.hpp b/include/boost/exception/detail/is_output_streamable.hpp new file mode 100644 index 0000000..badf4da --- /dev/null +++ b/include/boost/exception/detail/is_output_streamable.hpp @@ -0,0 +1,50 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//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 UUID_898984B4076411DD973EDFA055D89593 +#define UUID_898984B4076411DD973EDFA055D89593 + +#include + +namespace +boost + { + namespace + exception_detail + { + template + struct + is_output_streamable_dispatch + { + enum e { value=1 }; + }; + + template <> + struct + is_output_streamable_dispatch + { + enum e { value=0 }; + }; + + template + char operator<<( std::basic_ostream &, T const & ); + + template + struct + is_output_streamable_impl + { + enum e { value=is_output_streamable_dispatch<1!=sizeof((*(std::basic_ostream*)0)<<(*(T*)0))>::value }; + }; + } + + template > + struct + is_output_streamable + { + enum e { value=exception_detail::is_output_streamable_impl::value }; + }; + } + +#endif diff --git a/include/boost/exception/to_string.hpp b/include/boost/exception/to_string.hpp index 954797f..897f6f0 100644 --- a/include/boost/exception/to_string.hpp +++ b/include/boost/exception/to_string.hpp @@ -6,22 +6,62 @@ #ifndef UUID_7E48761AD92811DC9011477D56D89593 #define UUID_7E48761AD92811DC9011477D56D89593 +#include +#include #include -#include namespace boost { - namespace - { + namespace + exception_detail + { + template + struct + has_to_string_dispatch + { + enum e { value=1 }; + }; + + template <> + struct + has_to_string_dispatch + { + enum e { value=0 }; + }; + + template + std::string + to_string( T const & x, typename enable_if< is_output_streamable >::type * = 0 ) + { + std::ostringstream out; + out << x; + return out.str(); + } + template - std::string - to_string( T const & x ) - { - std::ostringstream out; - out << x; - return out.str(); - } + char to_string( T const &, typename disable_if< is_output_streamable >::type * = 0 ); + + template + struct + has_to_string_impl + { + enum e { value=has_to_string_dispatch<1!=sizeof(to_string(*(T*)0))>::value }; + }; + } + + template + struct + has_to_string + { + enum e { value=exception_detail::has_to_string_impl::value }; + }; + + template + std::string + to_string( T const & x, typename enable_if< is_output_streamable >::type * = 0 ) + { + return exception_detail::to_string(x); } } diff --git a/include/boost/exception/to_string_stub.hpp b/include/boost/exception/to_string_stub.hpp index ffefb5e..7e7d0e7 100644 --- a/include/boost/exception/to_string_stub.hpp +++ b/include/boost/exception/to_string_stub.hpp @@ -13,53 +13,6 @@ namespace boost { - namespace - exception_detail - { - template - struct shift_left_dispatcher; - - template <> - struct - shift_left_dispatcher - { - template - static - void - convert( std::basic_ostream & out, T const & x, Stub ) - { - out << x; - } - }; - - template <> - struct - shift_left_dispatcher - { - template - static - void - convert( std::basic_ostream & out, T const & x, Stub s ) - { - out << s(x); - } - }; - - namespace - shift_left_dispatch - { - template - char operator<<( std::basic_ostream &, T ); - - template - void - dispatch( std::basic_ostream & out, T const & x, Stub s ) - { - shift_left_dispatcher<1!=sizeof(out<::convert(out,x,s); - } - } - } - namespace exception_detail { @@ -82,26 +35,21 @@ boost { template static - std::string + std::string convert( T const & x, Stub s ) { - std::ostringstream out; - shift_left_dispatch::dispatch(out,x,s); - return out.str(); + return s(x); } }; namespace to_string_dispatch { - template - char to_string( T ); - template std::string dispatch( T const & x, Stub s ) { - return to_string_dispatcher<1!=sizeof(to_string(x))>::convert(x,s); + return to_string_dispatcher::value>::convert(x,s); } } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6e03750..879028b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -7,9 +7,15 @@ import testing ; +#to_string +run is_output_streamable_test.cpp ; +run to_string_test.cpp ; +run to_string_stub_test.cpp ; +compile-fail to_string_fail.cpp ; + +#exception run cloning_test.cpp ; run unknown_exception_test.cpp ; -run to_string_test.cpp ; run exception_test.cpp ; run boost_error_info_test.cpp ; run enable_error_info_test.cpp helper1.cpp ; diff --git a/test/is_output_streamable_test.cpp b/test/is_output_streamable_test.cpp new file mode 100644 index 0000000..d6fdf66 --- /dev/null +++ b/test/is_output_streamable_test.cpp @@ -0,0 +1,41 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//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) + +#include +#include + +namespace +n1 + { + class + c1 + { + }; + } + +namespace +n2 + { + class + c2 + { + }; + + std::ostream & + operator<<( std::ostream & s, c2 const & ) + { + s << "c2"; + return s; + } + } + +int +main() + { + BOOST_TEST( !boost::is_output_streamable::value ); + BOOST_TEST( boost::is_output_streamable::value ); + BOOST_TEST( boost::is_output_streamable::value ); + return boost::report_errors(); + } diff --git a/test/to_string_fail.cpp b/test/to_string_fail.cpp new file mode 100644 index 0000000..971d635 --- /dev/null +++ b/test/to_string_fail.cpp @@ -0,0 +1,23 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//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) + +#include + +namespace +n1 + { + struct + c1 + { + }; + } + +int +tester() + { + using namespace boost; + (void) to_string(n1::c1()); + return 1; + } diff --git a/test/to_string_stub_test.cpp b/test/to_string_stub_test.cpp new file mode 100644 index 0000000..d5d6518 --- /dev/null +++ b/test/to_string_stub_test.cpp @@ -0,0 +1,98 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//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) + +#include +#include +#include + +namespace +n1 + { + class + c1 + { + }; + + std::string + to_string( c1 const & ) + { + return "c1"; + } + } + +namespace +n2 + { + class + c2 + { + }; + + std::ostream & + operator<<( std::ostream & s, c2 const & ) + { + s << "c2"; + return s; + } + } + +namespace +n3 + { + class + c3 + { + }; + + std::ostream & + operator<<( std::ostream & s, c3 const & ) + { + s << "bad"; + return s; + } + + std::string + to_string( c3 const & ) + { + return "c3"; + } + } + +namespace +boost + { + class + to_string_tester + { + }; + } + +template +struct +my_stub + { + std::string + operator()( T const & ) + { + return "stub"; + } + }; + +int +main() + { + using namespace boost; + BOOST_TEST( to_string(42)=="42" ); + BOOST_TEST( to_string(n1::c1())=="c1" ); + BOOST_TEST( to_string(n2::c2())=="c2" ); + BOOST_TEST( to_string(n3::c3())=="c3" ); + BOOST_TEST( to_string_stub(42)=="42" ); + BOOST_TEST( to_string_stub(n1::c1())=="c1" ); + BOOST_TEST( to_string_stub(n2::c2())=="c2" ); + BOOST_TEST( to_string_stub(n3::c3())=="c3" ); + BOOST_TEST( to_string_stub(to_string_tester(),my_stub())=="stub" ); + BOOST_TEST( !to_string_stub(to_string_tester()).empty() ); + return boost::report_errors(); + } diff --git a/test/to_string_test.cpp b/test/to_string_test.cpp index c8dcd32..f722378 100644 --- a/test/to_string_test.cpp +++ b/test/to_string_test.cpp @@ -3,95 +3,58 @@ //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) -#include +#include #include -#include namespace n1 { - class + struct c1 { }; - - std::string - to_string( c1 const & ) - { - return "c1"; - } } namespace n2 { - class + struct c2 { }; - std::ostream & - operator<<( std::ostream & s, c2 const & ) + std::string + to_string( c2 const & ) { - s << "c2"; - return s; + return "c2"; } } namespace n3 { - class + struct c3 { }; - std::ostream & - operator<<( std::ostream & s, c3 const & ) + std::ostream & + operator<<( std::ostream & s, c3 const & ) { - s << "bad"; - return s; - } - - std::string - to_string( c3 const & ) - { - return "c3"; + return s << "c3"; } } -namespace -boost - { - class - to_string_tester - { - }; - } - -template -struct -my_stub - { - std::string - operator()( T const & ) - { - return "stub"; - } - }; - int main() { - using namespace boost; - BOOST_TEST( to_string(5)=="5" ); - BOOST_TEST( to_string(n1::c1())=="c1" ); - BOOST_TEST( to_string(n2::c2())=="c2" ); - BOOST_TEST( to_string(n3::c3())=="c3" ); - BOOST_TEST( to_string_stub(5)=="5" ); - BOOST_TEST( to_string_stub(n1::c1())=="c1" ); - BOOST_TEST( to_string_stub(n2::c2())=="c2" ); - BOOST_TEST( to_string_stub(n3::c3())=="c3" ); - BOOST_TEST( to_string_stub(to_string_tester(),my_stub())=="stub" ); + using namespace boost; + BOOST_TEST( !has_to_string::value ); + BOOST_TEST( has_to_string::value ); + BOOST_TEST( has_to_string::value ); + BOOST_TEST( has_to_string::value ); + BOOST_TEST( "c2"==to_string(n2::c2()) ); + BOOST_TEST( "c3"==to_string(n3::c3()) ); + BOOST_TEST( "42"==to_string(42) ); return boost::report_errors(); }