1 /*
2 * Copyright Andrey Semashev 2020.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * https://www.boost.org/LICENSE_1_0.txt)
6 */
7 /*!
8 * \file utility/manipulators/optional.hpp
9 * \author Andrey Semashev
10 * \date 12.05.2020
11 *
12 * The header contains implementation of a stream manipulator for inserting an optional value.
13 */
14
15 #ifndef BOOST_LOG_UTILITY_MANIPULATORS_OPTIONAL_HPP_INCLUDED_
16 #define BOOST_LOG_UTILITY_MANIPULATORS_OPTIONAL_HPP_INCLUDED_
17
18 #include <cstddef>
19 #include <boost/core/enable_if.hpp>
20 #include <boost/type_traits/is_array.hpp>
21 #include <boost/type_traits/is_scalar.hpp>
22 #include <boost/type_traits/conditional.hpp>
23 #include <boost/log/detail/config.hpp>
24 #include <boost/log/detail/is_ostream.hpp>
25 #include <boost/log/detail/header.hpp>
26
27 #ifdef BOOST_HAS_PRAGMA_ONCE
28 #pragma once
29 #endif
30
31 namespace boost {
32
33 BOOST_LOG_OPEN_NAMESPACE
34
35 /*!
36 * Stream manipulator for inserting an optional value.
37 */
38 template< typename OptionalT, typename NoneT >
39 class optional_manipulator
40 {
41 private:
42 typedef typename conditional<
43 is_scalar< OptionalT >::value,
44 OptionalT,
45 OptionalT const&
46 >::type stored_optional_type;
47
48 typedef typename conditional<
49 is_scalar< NoneT >::value,
50 NoneT,
51 NoneT const&
52 >::type stored_none_type;
53
54 private:
55 stored_optional_type m_optional;
56 stored_none_type m_none;
57
58 public:
59 //! Initializing constructor
optional_manipulator(stored_optional_type opt,stored_none_type none)60 optional_manipulator(stored_optional_type opt, stored_none_type none) BOOST_NOEXCEPT :
61 m_optional(opt),
62 m_none(none)
63 {
64 }
65
66 //! The method outputs the value, if it is present, otherwise outputs the "none" marker
67 template< typename StreamT >
output(StreamT & stream) const68 void output(StreamT& stream) const
69 {
70 if (!!m_optional)
71 stream << *m_optional;
72 else
73 stream << m_none;
74 }
75 };
76
77 /*!
78 * Stream manipulator for inserting an optional value. Specialization for no "none" marker.
79 */
80 template< typename OptionalT >
81 class optional_manipulator< OptionalT, void >
82 {
83 private:
84 typedef typename conditional<
85 is_scalar< OptionalT >::value,
86 OptionalT,
87 OptionalT const&
88 >::type stored_optional_type;
89
90 private:
91 stored_optional_type m_optional;
92
93 public:
94 //! Initializing constructor
optional_manipulator(stored_optional_type opt)95 optional_manipulator(stored_optional_type opt) BOOST_NOEXCEPT :
96 m_optional(opt)
97 {
98 }
99
100 //! The method outputs the value, if it is present
101 template< typename StreamT >
output(StreamT & stream) const102 void output(StreamT& stream) const
103 {
104 if (!!m_optional)
105 stream << *m_optional;
106 }
107 };
108
109 /*!
110 * Stream output operator for \c optional_manipulator. Outputs the optional value or the "none" marker, if one was specified on manipulator construction.
111 */
112 template< typename StreamT, typename OptionalT, typename NoneT >
operator <<(StreamT & strm,optional_manipulator<OptionalT,NoneT> const & manip)113 inline typename boost::enable_if_c< log::aux::is_ostream< StreamT >::value, StreamT& >::type operator<< (StreamT& strm, optional_manipulator< OptionalT, NoneT > const& manip)
114 {
115 manip.output(strm);
116 return strm;
117 }
118
119 /*!
120 * Optional manipulator generator function.
121 *
122 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
123 * \param none Marker used to indicate when the value is not present. Optional. If not specified, nothing is output if the value is not present.
124 * \returns Manipulator to be inserted into the stream.
125 *
126 * \note Both \a opt and \a none objects must outlive the created manipulator object.
127 */
128 template< typename OptionalT, typename NoneT >
129 inline typename boost::enable_if_c<
130 is_scalar< OptionalT >::value && is_scalar< NoneT >::value,
131 optional_manipulator< OptionalT, NoneT >
optional_manip(OptionalT opt,NoneT none)132 >::type optional_manip(OptionalT opt, NoneT none) BOOST_NOEXCEPT
133 {
134 return optional_manipulator< OptionalT, NoneT >(opt, none);
135 }
136
137 /*!
138 * Optional manipulator generator function.
139 *
140 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
141 * \param none Marker used to indicate when the value is not present. Optional. If not specified, nothing is output if the value is not present.
142 * \returns Manipulator to be inserted into the stream.
143 *
144 * \note Both \a opt and \a none objects must outlive the created manipulator object.
145 */
146 template< typename OptionalT, typename NoneT >
147 inline typename boost::enable_if_c<
148 is_scalar< OptionalT >::value && !is_scalar< NoneT >::value,
149 optional_manipulator< OptionalT, NoneT >
optional_manip(OptionalT opt,NoneT const & none)150 >::type optional_manip(OptionalT opt, NoneT const& none) BOOST_NOEXCEPT
151 {
152 return optional_manipulator< OptionalT, NoneT >(opt, none);
153 }
154
155 /*!
156 * Optional manipulator generator function.
157 *
158 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
159 * \param none Marker used to indicate when the value is not present. Optional. If not specified, nothing is output if the value is not present.
160 * \returns Manipulator to be inserted into the stream.
161 *
162 * \note Both \a opt and \a none objects must outlive the created manipulator object.
163 */
164 template< typename OptionalT, typename NoneElementT, std::size_t N >
165 inline typename boost::enable_if_c<
166 is_scalar< OptionalT >::value,
167 optional_manipulator< OptionalT, NoneElementT* >
optional_manip(OptionalT opt,NoneElementT (& none)[N])168 >::type optional_manip(OptionalT opt, NoneElementT (&none)[N]) BOOST_NOEXCEPT
169 {
170 return optional_manipulator< OptionalT, NoneElementT* >(opt, none);
171 }
172
173 /*!
174 * Optional manipulator generator function.
175 *
176 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
177 * \param none Marker used to indicate when the value is not present. Optional. If not specified, nothing is output if the value is not present.
178 * \returns Manipulator to be inserted into the stream.
179 *
180 * \note Both \a opt and \a none objects must outlive the created manipulator object.
181 */
182 template< typename OptionalT, typename NoneT >
183 inline typename boost::enable_if_c<
184 !is_scalar< OptionalT >::value && !is_array< OptionalT >::value && is_scalar< NoneT >::value,
185 optional_manipulator< OptionalT, NoneT >
optional_manip(OptionalT const & opt,NoneT none)186 >::type optional_manip(OptionalT const& opt, NoneT none) BOOST_NOEXCEPT
187 {
188 return optional_manipulator< OptionalT, NoneT >(opt, none);
189 }
190
191 /*!
192 * Optional manipulator generator function.
193 *
194 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
195 * \param none Marker used to indicate when the value is not present. Optional. If not specified, nothing is output if the value is not present.
196 * \returns Manipulator to be inserted into the stream.
197 *
198 * \note Both \a opt and \a none objects must outlive the created manipulator object.
199 */
200 template< typename OptionalT, typename NoneT >
201 inline typename boost::enable_if_c<
202 !is_scalar< OptionalT >::value && !is_array< OptionalT >::value && !is_scalar< NoneT >::value,
203 optional_manipulator< OptionalT, NoneT >
optional_manip(OptionalT const & opt,NoneT const & none)204 >::type optional_manip(OptionalT const& opt, NoneT const& none) BOOST_NOEXCEPT
205 {
206 return optional_manipulator< OptionalT, NoneT >(opt, none);
207 }
208
209 /*!
210 * Optional manipulator generator function.
211 *
212 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
213 * \param none Marker used to indicate when the value is not present. Optional. If not specified, nothing is output if the value is not present.
214 * \returns Manipulator to be inserted into the stream.
215 *
216 * \note Both \a opt and \a none objects must outlive the created manipulator object.
217 */
218 template< typename OptionalT, typename NoneElementT, std::size_t N >
219 inline typename boost::enable_if_c<
220 !is_scalar< OptionalT >::value && !is_array< OptionalT >::value,
221 optional_manipulator< OptionalT, NoneElementT* >
optional_manip(OptionalT const & opt,NoneElementT (& none)[N])222 >::type optional_manip(OptionalT const& opt, NoneElementT (&none)[N]) BOOST_NOEXCEPT
223 {
224 return optional_manipulator< OptionalT, NoneElementT* >(opt, none);
225 }
226
227 /*!
228 * Optional manipulator generator function.
229 *
230 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
231 * \returns Manipulator to be inserted into the stream.
232 *
233 * \note \a opt object must outlive the created manipulator object.
234 */
235 template< typename OptionalT >
236 inline typename boost::enable_if_c<
237 is_scalar< OptionalT >::value,
238 optional_manipulator< OptionalT, void >
optional_manip(OptionalT opt)239 >::type optional_manip(OptionalT opt) BOOST_NOEXCEPT
240 {
241 return optional_manipulator< OptionalT, void >(opt);
242 }
243
244 /*!
245 * Optional manipulator generator function.
246 *
247 * \param opt Optional value to output. The optional value must support contextual conversion to \c bool and dereferencing, and its dereferencing result must support stream output.
248 * \returns Manipulator to be inserted into the stream.
249 *
250 * \note \a opt object must outlive the created manipulator object.
251 */
252 template< typename OptionalT >
253 inline typename boost::enable_if_c<
254 !is_scalar< OptionalT >::value && !is_array< OptionalT >::value,
255 optional_manipulator< OptionalT, void >
optional_manip(OptionalT const & opt)256 >::type optional_manip(OptionalT const& opt) BOOST_NOEXCEPT
257 {
258 return optional_manipulator< OptionalT, void >(opt);
259 }
260
261 BOOST_LOG_CLOSE_NAMESPACE // namespace log
262
263 } // namespace boost
264
265 #include <boost/log/detail/footer.hpp>
266
267 #endif // BOOST_LOG_UTILITY_MANIPULATORS_OPTIONAL_HPP_INCLUDED_
268