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( 2 + 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<char const*> { |
158 | void operator()( std::ostream& ostr, char const* t ); |
159 | }; |
160 | |
161 | //____________________________________________________________________________// |
162 | |
163 | template<> |
164 | struct BOOST_TEST_DECL print_log_value<wchar_t const*> { |
165 | void operator()( std::ostream& ostr, wchar_t const* t ); |
166 | }; |
167 | |
168 | #if !defined(BOOST_NO_CXX11_NULLPTR) |
169 | template<> |
170 | struct print_log_value<std::nullptr_t> { |
171 | // declaration and definition is here because of #12969 https://svn.boost.org/trac10/ticket/12969 |
172 | void operator()( std::ostream& ostr, std::nullptr_t /*t*/ ) { |
173 | ostr << "nullptr" ; |
174 | } |
175 | }; |
176 | #endif |
177 | |
178 | //____________________________________________________________________________// |
179 | |
180 | // ************************************************************************** // |
181 | // ************** print_helper ************** // |
182 | // ************************************************************************** // |
183 | // Adds level of indirection to the output operation, allowing us to customize |
184 | // it for types that do not support operator << directly or for any other reason |
185 | |
186 | template<typename T> |
187 | struct print_helper_t { |
188 | explicit print_helper_t( T const& t ) : m_t( t ) {} |
189 | |
190 | T const& m_t; |
191 | }; |
192 | |
193 | //____________________________________________________________________________// |
194 | |
195 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
196 | // Borland suffers premature pointer decay passing arrays by reference |
197 | template<typename T, std::size_t N > |
198 | struct print_helper_t< T[N] > { |
199 | explicit print_helper_t( T const * t ) : m_t( t ) {} |
200 | |
201 | T const * m_t; |
202 | }; |
203 | #endif |
204 | |
205 | //____________________________________________________________________________// |
206 | |
207 | template<typename T> |
208 | inline print_helper_t<T> |
209 | print_helper( T const& t ) |
210 | { |
211 | return print_helper_t<T>( t ); |
212 | } |
213 | |
214 | //____________________________________________________________________________// |
215 | |
216 | template<typename T> |
217 | inline std::ostream& |
218 | operator<<( std::ostream& ostr, print_helper_t<T> const& ph ) |
219 | { |
220 | print_log_value<T>()( ostr, ph.m_t ); |
221 | |
222 | return ostr; |
223 | } |
224 | |
225 | //____________________________________________________________________________// |
226 | |
227 | } // namespace tt_detail |
228 | |
229 | // ************************************************************************** // |
230 | // ************** BOOST_TEST_DONT_PRINT_LOG_VALUE ************** // |
231 | // ************************************************************************** // |
232 | |
233 | #define BOOST_TEST_DONT_PRINT_LOG_VALUE( the_type ) \ |
234 | namespace boost{ namespace test_tools{ namespace tt_detail{ \ |
235 | template<> \ |
236 | struct print_log_value<the_type > { \ |
237 | void operator()( std::ostream&, the_type const& ) {} \ |
238 | }; \ |
239 | }}} \ |
240 | /**/ |
241 | |
242 | } // namespace test_tools |
243 | } // namespace boost |
244 | |
245 | #include <boost/test/detail/enable_warnings.hpp> |
246 | |
247 | #endif // BOOST_TEST_TOOLS_IMPL_COMMON_HPP_012705GER |
248 | |