• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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