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 | |
22 | // Boost |
23 | #include <boost/mpl/or.hpp> |
24 | #include <boost/static_assert.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 <boost/type_traits/has_left_shift.hpp> |
29 | |
30 | #include <ios> |
31 | #include <iostream> |
32 | #include <limits> |
33 | |
34 | #if !defined(BOOST_NO_CXX11_NULLPTR) |
35 | #include <cstddef> |
36 | #endif |
37 | |
38 | #include <boost/test/detail/suppress_warnings.hpp> |
39 | |
40 | //____________________________________________________________________________// |
41 | |
42 | namespace boost { |
43 | namespace test_tools { |
44 | namespace tt_detail { |
45 | |
46 | // ************************************************************************** // |
47 | // ************** boost_test_print_type ************** // |
48 | // ************************************************************************** // |
49 | |
50 | namespace impl { |
51 | template <class T> |
52 | std::ostream& boost_test_print_type(std::ostream& ostr, T const& t) { |
53 | BOOST_STATIC_ASSERT_MSG( (boost::has_left_shift<std::ostream,T>::value), |
54 | "Type has to implement operator<< to be printable" ); |
55 | ostr << t; |
56 | return ostr; |
57 | } |
58 | |
59 | struct boost_test_print_type_impl { |
60 | template <class R> |
61 | std::ostream& operator()(std::ostream& ostr, R const& r) const { |
62 | return boost_test_print_type(ostr, r); |
63 | } |
64 | }; |
65 | } |
66 | |
67 | // To avoid ODR violations, see N4381 |
68 | template <class T> struct static_const { static const T value; }; |
69 | template <class T> const T static_const<T>::value = T(); |
70 | |
71 | namespace { |
72 | static const impl::boost_test_print_type_impl& boost_test_print_type = |
73 | static_const<impl::boost_test_print_type_impl>::value; |
74 | } |
75 | |
76 | |
77 | // ************************************************************************** // |
78 | // ************** print_log_value ************** // |
79 | // ************************************************************************** // |
80 | |
81 | template<typename T> |
82 | struct print_log_value { |
83 | void operator()( std::ostream& ostr, T const& t ) |
84 | { |
85 | typedef typename mpl::or_<is_array<T>,is_function<T>,is_abstract<T> >::type cant_use_nl; |
86 | |
87 | std::streamsize old_precision = set_precision( ostr, cant_use_nl() ); |
88 | |
89 | //ostr << t; |
90 | using boost::test_tools::tt_detail::boost_test_print_type; |
91 | boost_test_print_type(ostr, t); |
92 | |
93 | if( old_precision != (std::streamsize)-1 ) |
94 | ostr.precision( prec: old_precision ); |
95 | } |
96 | |
97 | std::streamsize set_precision( std::ostream& ostr, mpl::false_ ) |
98 | { |
99 | if( std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 2 ) |
100 | return ostr.precision( prec: 2 + std::streamsize(std::numeric_limits<T>::digits) * 301/1000 ); |
101 | else if ( std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::radix == 10 ) { |
102 | #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS |
103 | // (was BOOST_NO_NUMERIC_LIMITS_LOWEST but now deprecated). |
104 | // No support for std::numeric_limits<double>::max_digits10, |
105 | // so guess that a couple of guard digits more than digits10 will display any difference. |
106 | return ostr.precision( 2 + std::numeric_limits<T>::digits10 ); |
107 | #else |
108 | // std::numeric_limits<double>::max_digits10; IS supported. |
109 | // Any noisy or guard digits needed to display any difference are included in max_digits10. |
110 | return ostr.precision( std::numeric_limits<T>::max_digits10 ); |
111 | #endif |
112 | } |
113 | // else if T is not specialized for std::numeric_limits<>, |
114 | // then will just get the default precision of 6 digits. |
115 | return (std::streamsize)-1; |
116 | } |
117 | |
118 | std::streamsize set_precision( std::ostream&, mpl::true_ ) { return (std::streamsize)-1; } |
119 | }; |
120 | |
121 | //____________________________________________________________________________// |
122 | |
123 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
124 | template<typename T, std::size_t N > |
125 | struct print_log_value< T[N] > { |
126 | void operator()( std::ostream& ostr, T const* t ) |
127 | { |
128 | ostr << t; |
129 | } |
130 | }; |
131 | #endif |
132 | |
133 | //____________________________________________________________________________// |
134 | |
135 | template<> |
136 | struct BOOST_TEST_DECL print_log_value<bool> { |
137 | void operator()( std::ostream& ostr, bool t ); |
138 | }; |
139 | |
140 | //____________________________________________________________________________// |
141 | |
142 | template<> |
143 | struct BOOST_TEST_DECL print_log_value<char> { |
144 | void operator()( std::ostream& ostr, char t ); |
145 | }; |
146 | |
147 | //____________________________________________________________________________// |
148 | |
149 | template<> |
150 | struct BOOST_TEST_DECL print_log_value<unsigned char> { |
151 | void operator()( std::ostream& ostr, unsigned char t ); |
152 | }; |
153 | |
154 | //____________________________________________________________________________// |
155 | |
156 | template<> |
157 | struct BOOST_TEST_DECL print_log_value<wchar_t> { |
158 | void operator()( std::ostream& ostr, wchar_t t ); |
159 | }; |
160 | |
161 | //____________________________________________________________________________// |
162 | |
163 | template<> |
164 | struct BOOST_TEST_DECL print_log_value<char const*> { |
165 | void operator()( std::ostream& ostr, char const* t ); |
166 | }; |
167 | |
168 | //____________________________________________________________________________// |
169 | |
170 | template<> |
171 | struct BOOST_TEST_DECL print_log_value<wchar_t const*> { |
172 | void operator()( std::ostream& ostr, wchar_t const* t ); |
173 | }; |
174 | |
175 | #if !defined(BOOST_NO_CXX11_NULLPTR) |
176 | template<> |
177 | struct print_log_value<std::nullptr_t> { |
178 | // declaration and definition is here because of #12969 https://svn.boost.org/trac10/ticket/12969 |
179 | void operator()( std::ostream& ostr, std::nullptr_t /*t*/ ) { |
180 | ostr << "nullptr" ; |
181 | } |
182 | }; |
183 | #endif |
184 | |
185 | //____________________________________________________________________________// |
186 | |
187 | // ************************************************************************** // |
188 | // ************** print_helper ************** // |
189 | // ************************************************************************** // |
190 | // Adds level of indirection to the output operation, allowing us to customize |
191 | // it for types that do not support operator << directly or for any other reason |
192 | |
193 | template<typename T> |
194 | struct print_helper_t { |
195 | explicit print_helper_t( T const& t ) : m_t( t ) {} |
196 | |
197 | T const& m_t; |
198 | }; |
199 | |
200 | //____________________________________________________________________________// |
201 | |
202 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
203 | // Borland suffers premature pointer decay passing arrays by reference |
204 | template<typename T, std::size_t N > |
205 | struct print_helper_t< T[N] > { |
206 | explicit print_helper_t( T const * t ) : m_t( t ) {} |
207 | |
208 | T const * m_t; |
209 | }; |
210 | #endif |
211 | |
212 | //____________________________________________________________________________// |
213 | |
214 | template<typename T> |
215 | inline print_helper_t<T> |
216 | print_helper( T const& t ) |
217 | { |
218 | return print_helper_t<T>( t ); |
219 | } |
220 | |
221 | //____________________________________________________________________________// |
222 | |
223 | template<typename T> |
224 | inline std::ostream& |
225 | operator<<( std::ostream& ostr, print_helper_t<T> const& ph ) |
226 | { |
227 | print_log_value<T>()( ostr, ph.m_t ); |
228 | |
229 | return ostr; |
230 | } |
231 | |
232 | //____________________________________________________________________________// |
233 | |
234 | } // namespace tt_detail |
235 | |
236 | // ************************************************************************** // |
237 | // ************** BOOST_TEST_DONT_PRINT_LOG_VALUE ************** // |
238 | // ************************************************************************** // |
239 | |
240 | #define BOOST_TEST_DONT_PRINT_LOG_VALUE( the_type ) \ |
241 | namespace boost{ namespace test_tools{ namespace tt_detail{ \ |
242 | template<> \ |
243 | struct print_log_value<the_type > { \ |
244 | void operator()( std::ostream&, the_type const& ) {} \ |
245 | }; \ |
246 | }}} \ |
247 | /**/ |
248 | |
249 | } // namespace test_tools |
250 | } // namespace boost |
251 | |
252 | #include <boost/test/detail/enable_warnings.hpp> |
253 | |
254 | #endif // BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER |
255 | |