1 | // (C) Copyright Gennadiy Rozental 2001. |
2 | // Distributed under the Boost Software License, Version 1.0. |
3 | // (See accompanying file LICENSE_1_0.txt or copy at |
4 | // http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | // See http://www.boost.org/libs/test for the library home page. |
7 | // |
8 | // File : $RCSfile$ |
9 | // |
10 | // Version : $Revision: 74248 $ |
11 | // |
12 | // Description : defines level of indiration facilitating workarounds for non printable types |
13 | // *************************************************************************** |
14 | |
15 | #ifndef BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER |
16 | #define BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER |
17 | |
18 | // Boost.Test |
19 | #include <boost/test/detail/config.hpp> |
20 | #include <boost/test/detail/global_typedef.hpp> |
21 | #include <boost/test/detail/workaround.hpp> |
22 | |
23 | // Boost |
24 | #include <boost/mpl/or.hpp> |
25 | #include <boost/type_traits/is_array.hpp> |
26 | #include <boost/type_traits/is_function.hpp> |
27 | #include <boost/type_traits/is_abstract.hpp> |
28 | #include <limits> |
29 | |
30 | #include <boost/test/detail/suppress_warnings.hpp> |
31 | |
32 | //____________________________________________________________________________// |
33 | |
34 | namespace boost { |
35 | namespace test_tools { |
36 | namespace tt_detail { |
37 | |
38 | // ************************************************************************** // |
39 | // ************** print_log_value ************** // |
40 | // ************************************************************************** // |
41 | |
42 | template<typename T> |
43 | struct print_log_value { |
44 | void operator()( std::ostream& ostr, T const& t ) |
45 | { |
46 | typedef typename mpl::or_<is_array<T>,is_function<T>,is_abstract<T> >::type cant_use_nl; |
47 | |
48 | std::streamsize old_precision = set_precision( ostr, cant_use_nl() ); |
49 | |
50 | ostr << t; |
51 | |
52 | if( old_precision != (std::streamsize)-1 ) |
53 | ostr.precision( prec: old_precision ); |
54 | } |
55 | |
56 | std::streamsize set_precision( std::ostream& ostr, mpl::false_ ) |
57 | { |
58 | if( std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 2 ) |
59 | return ostr.precision( 2 + std::numeric_limits<T>::digits * 301/1000 ); |
60 | else if ( std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 10 ) { |
61 | #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS |
62 | // (was BOOST_NO_NUMERIC_LIMITS_LOWEST but now deprecated). |
63 | // No support for std::numeric_limits<double>::max_digits10, |
64 | // so guess that a couple of guard digits more than digits10 will display any difference. |
65 | return ostr.precision( 2 + std::numeric_limits<T>::digits10 ); |
66 | #else |
67 | // std::numeric_limits<double>::max_digits10; IS supported. |
68 | // Any noisy or guard digits needed to display any difference are included in max_digits10. |
69 | return ostr.precision( std::numeric_limits<T>::max_digits10 ); |
70 | #endif |
71 | } |
72 | // else if T is not specialized for std::numeric_limits<>, |
73 | // then will just get the default precision of 6 digits. |
74 | return (std::streamsize)-1; |
75 | } |
76 | |
77 | std::streamsize set_precision( std::ostream&, mpl::true_ ) { return (std::streamsize)-1; } |
78 | }; |
79 | |
80 | //____________________________________________________________________________// |
81 | |
82 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
83 | template<typename T, std::size_t N > |
84 | struct print_log_value< T[N] > { |
85 | void operator()( std::ostream& ostr, T const* t ) |
86 | { |
87 | ostr << t; |
88 | } |
89 | }; |
90 | #endif |
91 | |
92 | //____________________________________________________________________________// |
93 | |
94 | template<> |
95 | struct BOOST_TEST_DECL print_log_value<bool> { |
96 | void operator()( std::ostream& ostr, bool t ) |
97 | { |
98 | ostr << std::boolalpha << t; |
99 | } |
100 | }; |
101 | |
102 | //____________________________________________________________________________// |
103 | |
104 | template<> |
105 | struct BOOST_TEST_DECL print_log_value<char> { |
106 | void operator()( std::ostream& ostr, char t ); |
107 | }; |
108 | |
109 | //____________________________________________________________________________// |
110 | |
111 | template<> |
112 | struct BOOST_TEST_DECL print_log_value<unsigned char> { |
113 | void operator()( std::ostream& ostr, unsigned char t ); |
114 | }; |
115 | |
116 | //____________________________________________________________________________// |
117 | |
118 | template<> |
119 | struct BOOST_TEST_DECL print_log_value<char const*> { |
120 | void operator()( std::ostream& ostr, char const* t ); |
121 | }; |
122 | |
123 | //____________________________________________________________________________// |
124 | |
125 | template<> |
126 | struct BOOST_TEST_DECL print_log_value<wchar_t const*> { |
127 | void operator()( std::ostream& ostr, wchar_t const* t ); |
128 | }; |
129 | |
130 | //____________________________________________________________________________// |
131 | |
132 | // ************************************************************************** // |
133 | // ************** print_helper ************** // |
134 | // ************************************************************************** // |
135 | // Adds level of indirection to the output operation, allowing us to customize |
136 | // it for types that do not support operator << directly or for any other reason |
137 | |
138 | template<typename T> |
139 | struct print_helper_t { |
140 | explicit print_helper_t( T const& t ) : m_t( t ) {} |
141 | |
142 | T const& m_t; |
143 | }; |
144 | |
145 | //____________________________________________________________________________// |
146 | |
147 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
148 | // Borland suffers premature pointer decay passing arrays by reference |
149 | template<typename T, std::size_t N > |
150 | struct print_helper_t< T[N] > { |
151 | explicit print_helper_t( T const * t ) : m_t( t ) {} |
152 | |
153 | T const * m_t; |
154 | }; |
155 | #endif |
156 | |
157 | //____________________________________________________________________________// |
158 | |
159 | template<typename T> |
160 | inline print_helper_t<T> |
161 | print_helper( T const& t ) |
162 | { |
163 | return print_helper_t<T>( t ); |
164 | } |
165 | |
166 | //____________________________________________________________________________// |
167 | |
168 | template<typename T> |
169 | inline std::ostream& |
170 | operator<<( std::ostream& ostr, print_helper_t<T> const& ph ) |
171 | { |
172 | print_log_value<T>()( ostr, ph.m_t ); |
173 | |
174 | return ostr; |
175 | } |
176 | |
177 | //____________________________________________________________________________// |
178 | |
179 | } // namespace tt_detail |
180 | |
181 | // ************************************************************************** // |
182 | // ************** BOOST_TEST_DONT_PRINT_LOG_VALUE ************** // |
183 | // ************************************************************************** // |
184 | |
185 | #define BOOST_TEST_DONT_PRINT_LOG_VALUE( the_type ) \ |
186 | namespace boost{ namespace test_tools{ namespace tt_detail{ \ |
187 | template<> \ |
188 | struct print_log_value<the_type > { \ |
189 | void operator()( std::ostream&, the_type const& ) {} \ |
190 | }; \ |
191 | }}} \ |
192 | /**/ |
193 | |
194 | } // namespace test_tools |
195 | } // namespace boost |
196 | |
197 | #include <boost/test/detail/enable_warnings.hpp> |
198 | |
199 | #endif // BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER |
200 | |