]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
7c673cae FG |
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 | ||
92f5a8d4 TL |
30 | #include <ios> |
31 | #include <iostream> | |
7c673cae FG |
32 | #include <limits> |
33 | ||
b32b8144 FG |
34 | #if !defined(BOOST_NO_CXX11_NULLPTR) |
35 | #include <cstddef> | |
36 | #endif | |
37 | ||
7c673cae FG |
38 | #include <boost/test/detail/suppress_warnings.hpp> |
39 | ||
40 | //____________________________________________________________________________// | |
41 | ||
42 | namespace boost { | |
43 | namespace test_tools { | |
44 | namespace tt_detail { | |
45 | ||
b32b8144 FG |
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 | ||
7c673cae FG |
77 | // ************************************************************************** // |
78 | // ************** print_log_value ************** // | |
79 | // ************************************************************************** // | |
80 | ||
81 | template<typename T> | |
82 | struct print_log_value { | |
7c673cae FG |
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 | ||
b32b8144 FG |
89 | //ostr << t; |
90 | using boost::test_tools::tt_detail::boost_test_print_type; | |
91 | boost_test_print_type(ostr, t); | |
7c673cae FG |
92 | |
93 | if( old_precision != (std::streamsize)-1 ) | |
94 | ostr.precision( 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(__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> { | |
b32b8144 | 137 | void operator()( std::ostream& ostr, bool t ); |
7c673cae FG |
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 | ||
b32b8144 FG |
168 | #if !defined(BOOST_NO_CXX11_NULLPTR) |
169 | template<> | |
11fdf7f2 TL |
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 | } | |
b32b8144 FG |
175 | }; |
176 | #endif | |
177 | ||
7c673cae FG |
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(__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 |