optional.hpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #ifndef BOOST_LOG_UTILITY_MANIPULATORS_OPTIONAL_HPP_INCLUDED_
  15. #define BOOST_LOG_UTILITY_MANIPULATORS_OPTIONAL_HPP_INCLUDED_
  16. #include <cstddef>
  17. #include <boost/core/enable_if.hpp>
  18. #include <boost/type_traits/is_array.hpp>
  19. #include <boost/type_traits/is_scalar.hpp>
  20. #include <boost/type_traits/conditional.hpp>
  21. #include <boost/log/detail/config.hpp>
  22. #include <boost/log/detail/is_ostream.hpp>
  23. #include <boost/log/detail/header.hpp>
  24. #ifdef BOOST_HAS_PRAGMA_ONCE
  25. #pragma once
  26. #endif
  27. namespace boost {
  28. BOOST_LOG_OPEN_NAMESPACE
  29. /*!
  30. * Stream manipulator for inserting an optional value.
  31. */
  32. template< typename OptionalT, typename NoneT >
  33. class optional_manipulator
  34. {
  35. private:
  36. typedef typename conditional<
  37. is_scalar< OptionalT >::value,
  38. OptionalT,
  39. OptionalT const&
  40. >::type stored_optional_type;
  41. typedef typename conditional<
  42. is_scalar< NoneT >::value,
  43. NoneT,
  44. NoneT const&
  45. >::type stored_none_type;
  46. private:
  47. stored_optional_type m_optional;
  48. stored_none_type m_none;
  49. public:
  50. //! Initializing constructor
  51. optional_manipulator(stored_optional_type opt, stored_none_type none) BOOST_NOEXCEPT :
  52. m_optional(opt),
  53. m_none(none)
  54. {
  55. }
  56. //! The method outputs the value, if it is present, otherwise outputs the "none" marker
  57. template< typename StreamT >
  58. void output(StreamT& stream) const
  59. {
  60. if (!!m_optional)
  61. stream << *m_optional;
  62. else
  63. stream << m_none;
  64. }
  65. };
  66. /*!
  67. * Stream manipulator for inserting an optional value. Specialization for no "none" marker.
  68. */
  69. template< typename OptionalT >
  70. class optional_manipulator< OptionalT, void >
  71. {
  72. private:
  73. typedef typename conditional<
  74. is_scalar< OptionalT >::value,
  75. OptionalT,
  76. OptionalT const&
  77. >::type stored_optional_type;
  78. private:
  79. stored_optional_type m_optional;
  80. public:
  81. //! Initializing constructor
  82. optional_manipulator(stored_optional_type opt) BOOST_NOEXCEPT :
  83. m_optional(opt)
  84. {
  85. }
  86. //! The method outputs the value, if it is present
  87. template< typename StreamT >
  88. void output(StreamT& stream) const
  89. {
  90. if (!!m_optional)
  91. stream << *m_optional;
  92. }
  93. };
  94. /*!
  95. * Stream output operator for \c optional_manipulator. Outputs the optional value or the "none" marker, if one was specified on manipulator construction.
  96. */
  97. template< typename StreamT, typename OptionalT, typename NoneT >
  98. inline typename boost::enable_if_c< log::aux::is_ostream< StreamT >::value, StreamT& >::type operator<< (StreamT& strm, optional_manipulator< OptionalT, NoneT > const& manip)
  99. {
  100. manip.output(strm);
  101. return strm;
  102. }
  103. /*!
  104. * Optional manipulator generator function.
  105. *
  106. * \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.
  107. * \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.
  108. * \returns Manipulator to be inserted into the stream.
  109. *
  110. * \note Both \a opt and \a none objects must outlive the created manipulator object.
  111. */
  112. template< typename OptionalT, typename NoneT >
  113. inline typename boost::enable_if_c<
  114. is_scalar< OptionalT >::value && is_scalar< NoneT >::value,
  115. optional_manipulator< OptionalT, NoneT >
  116. >::type optional_manip(OptionalT opt, NoneT none) BOOST_NOEXCEPT
  117. {
  118. return optional_manipulator< OptionalT, NoneT >(opt, none);
  119. }
  120. /*!
  121. * Optional manipulator generator function.
  122. *
  123. * \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.
  124. * \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.
  125. * \returns Manipulator to be inserted into the stream.
  126. *
  127. * \note Both \a opt and \a none objects must outlive the created manipulator object.
  128. */
  129. template< typename OptionalT, typename NoneT >
  130. inline typename boost::enable_if_c<
  131. is_scalar< OptionalT >::value && !is_scalar< NoneT >::value,
  132. optional_manipulator< OptionalT, NoneT >
  133. >::type optional_manip(OptionalT opt, NoneT const& none) BOOST_NOEXCEPT
  134. {
  135. return optional_manipulator< OptionalT, NoneT >(opt, none);
  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 NoneElementT, std::size_t N >
  147. inline typename boost::enable_if_c<
  148. is_scalar< OptionalT >::value,
  149. optional_manipulator< OptionalT, NoneElementT* >
  150. >::type optional_manip(OptionalT opt, NoneElementT (&none)[N]) BOOST_NOEXCEPT
  151. {
  152. return optional_manipulator< OptionalT, NoneElementT* >(opt, none);
  153. }
  154. /*!
  155. * Optional manipulator generator function.
  156. *
  157. * \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.
  158. * \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.
  159. * \returns Manipulator to be inserted into the stream.
  160. *
  161. * \note Both \a opt and \a none objects must outlive the created manipulator object.
  162. */
  163. template< typename OptionalT, typename NoneT >
  164. inline typename boost::enable_if_c<
  165. !is_scalar< OptionalT >::value && !is_array< OptionalT >::value && is_scalar< NoneT >::value,
  166. optional_manipulator< OptionalT, NoneT >
  167. >::type optional_manip(OptionalT const& opt, NoneT none) BOOST_NOEXCEPT
  168. {
  169. return optional_manipulator< OptionalT, NoneT >(opt, none);
  170. }
  171. /*!
  172. * Optional manipulator generator function.
  173. *
  174. * \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.
  175. * \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.
  176. * \returns Manipulator to be inserted into the stream.
  177. *
  178. * \note Both \a opt and \a none objects must outlive the created manipulator object.
  179. */
  180. template< typename OptionalT, typename NoneT >
  181. inline typename boost::enable_if_c<
  182. !is_scalar< OptionalT >::value && !is_array< OptionalT >::value && !is_scalar< NoneT >::value,
  183. optional_manipulator< OptionalT, NoneT >
  184. >::type optional_manip(OptionalT const& opt, NoneT const& none) BOOST_NOEXCEPT
  185. {
  186. return optional_manipulator< OptionalT, NoneT >(opt, none);
  187. }
  188. /*!
  189. * Optional manipulator generator function.
  190. *
  191. * \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.
  192. * \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.
  193. * \returns Manipulator to be inserted into the stream.
  194. *
  195. * \note Both \a opt and \a none objects must outlive the created manipulator object.
  196. */
  197. template< typename OptionalT, typename NoneElementT, std::size_t N >
  198. inline typename boost::enable_if_c<
  199. !is_scalar< OptionalT >::value && !is_array< OptionalT >::value,
  200. optional_manipulator< OptionalT, NoneElementT* >
  201. >::type optional_manip(OptionalT const& opt, NoneElementT (&none)[N]) BOOST_NOEXCEPT
  202. {
  203. return optional_manipulator< OptionalT, NoneElementT* >(opt, none);
  204. }
  205. /*!
  206. * Optional manipulator generator function.
  207. *
  208. * \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.
  209. * \returns Manipulator to be inserted into the stream.
  210. *
  211. * \note \a opt object must outlive the created manipulator object.
  212. */
  213. template< typename OptionalT >
  214. inline typename boost::enable_if_c<
  215. is_scalar< OptionalT >::value,
  216. optional_manipulator< OptionalT, void >
  217. >::type optional_manip(OptionalT opt) BOOST_NOEXCEPT
  218. {
  219. return optional_manipulator< OptionalT, void >(opt);
  220. }
  221. /*!
  222. * Optional manipulator generator function.
  223. *
  224. * \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.
  225. * \returns Manipulator to be inserted into the stream.
  226. *
  227. * \note \a opt object must outlive the created manipulator object.
  228. */
  229. template< typename OptionalT >
  230. inline typename boost::enable_if_c<
  231. !is_scalar< OptionalT >::value && !is_array< OptionalT >::value,
  232. optional_manipulator< OptionalT, void >
  233. >::type optional_manip(OptionalT const& opt) BOOST_NOEXCEPT
  234. {
  235. return optional_manipulator< OptionalT, void >(opt);
  236. }
  237. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  238. } // namespace boost
  239. #include <boost/log/detail/footer.hpp>
  240. #endif // BOOST_LOG_UTILITY_MANIPULATORS_OPTIONAL_HPP_INCLUDED_