if.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2015.
  3. * Distributed under the Boost Software License, Version 1.0.
  4. * (See accompanying file LICENSE_1_0.txt or copy at
  5. * http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. /*!
  8. * \file formatters/if.hpp
  9. * \author Andrey Semashev
  10. * \date 17.11.2012
  11. *
  12. * The header contains implementation of a conditional formatter.
  13. */
  14. #ifndef BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_
  15. #define BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_
  16. #include <boost/mpl/bool.hpp>
  17. #include <boost/phoenix/core/actor.hpp>
  18. #include <boost/phoenix/core/meta_grammar.hpp>
  19. #include <boost/phoenix/core/terminal_fwd.hpp>
  20. #include <boost/phoenix/core/is_nullary.hpp>
  21. #include <boost/phoenix/core/environment.hpp>
  22. #include <boost/fusion/sequence/intrinsic/at_c.hpp>
  23. #include <boost/type_traits/remove_cv.hpp>
  24. #include <boost/type_traits/remove_reference.hpp>
  25. #include <boost/log/detail/config.hpp>
  26. #include <boost/log/detail/custom_terminal_spec.hpp>
  27. #include <boost/log/detail/header.hpp>
  28. #ifdef BOOST_HAS_PRAGMA_ONCE
  29. #pragma once
  30. #endif
  31. namespace boost {
  32. BOOST_LOG_OPEN_NAMESPACE
  33. namespace expressions {
  34. namespace aux {
  35. template< typename LeftT, typename CondT, typename ThenT >
  36. class if_output_terminal
  37. {
  38. private:
  39. //! Self type
  40. typedef if_output_terminal this_type;
  41. public:
  42. #ifndef BOOST_LOG_DOXYGEN_PASS
  43. //! Internal typedef for type categorization
  44. typedef void _is_boost_log_terminal;
  45. #endif
  46. //! Result type definition
  47. template< typename >
  48. struct result;
  49. template< typename ThisT, typename ContextT >
  50. struct result< ThisT(ContextT) >
  51. {
  52. typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
  53. typedef typename phoenix::evaluator::impl<
  54. typename LeftT::proto_base_expr&,
  55. context_type,
  56. phoenix::unused
  57. >::result_type type;
  58. };
  59. private:
  60. //! Left argument actor
  61. LeftT m_left;
  62. //! Condition expression
  63. CondT m_cond;
  64. //! Positive branch
  65. ThenT m_then;
  66. public:
  67. //! Initializing constructor
  68. if_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_) : m_left(left), m_cond(cond), m_then(then_)
  69. {
  70. }
  71. //! Invokation operator
  72. template< typename ContextT >
  73. typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
  74. {
  75. typedef typename result< this_type(ContextT const&) >::type result_type;
  76. result_type strm = phoenix::eval(m_left, ctx);
  77. if (phoenix::eval(m_cond, ctx))
  78. phoenix::eval(m_then, ctx);
  79. return strm;
  80. }
  81. //! Invokation operator
  82. template< typename ContextT >
  83. typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
  84. {
  85. typedef typename result< const this_type(ContextT const&) >::type result_type;
  86. result_type strm = phoenix::eval(m_left, ctx);
  87. if (phoenix::eval(m_cond, ctx))
  88. phoenix::eval(m_then, ctx);
  89. return strm;
  90. }
  91. BOOST_DELETED_FUNCTION(if_output_terminal())
  92. };
  93. template< typename LeftT, typename CondT, typename ThenT, typename ElseT >
  94. class if_else_output_terminal
  95. {
  96. private:
  97. //! Self type
  98. typedef if_else_output_terminal this_type;
  99. public:
  100. #ifndef BOOST_LOG_DOXYGEN_PASS
  101. //! Internal typedef for type categorization
  102. typedef void _is_boost_log_terminal;
  103. #endif
  104. //! Result type definition
  105. template< typename >
  106. struct result;
  107. template< typename ThisT, typename ContextT >
  108. struct result< ThisT(ContextT) >
  109. {
  110. typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type;
  111. typedef typename phoenix::evaluator::impl<
  112. typename LeftT::proto_base_expr&,
  113. context_type,
  114. phoenix::unused
  115. >::result_type type;
  116. };
  117. private:
  118. //! Left argument actor
  119. LeftT m_left;
  120. //! Condition expression
  121. CondT m_cond;
  122. //! Positive branch
  123. ThenT m_then;
  124. //! Negative branch
  125. ElseT m_else;
  126. public:
  127. //! Initializing constructor
  128. if_else_output_terminal(LeftT const& left, CondT const& cond, ThenT const& then_, ElseT const& else_) : m_left(left), m_cond(cond), m_then(then_), m_else(else_)
  129. {
  130. }
  131. //! Invokation operator
  132. template< typename ContextT >
  133. typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx)
  134. {
  135. typedef typename result< this_type(ContextT const&) >::type result_type;
  136. result_type strm = phoenix::eval(m_left, ctx);
  137. if (phoenix::eval(m_cond, ctx))
  138. phoenix::eval(m_then, ctx);
  139. else
  140. phoenix::eval(m_else, ctx);
  141. return strm;
  142. }
  143. //! Invokation operator
  144. template< typename ContextT >
  145. typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const
  146. {
  147. typedef typename result< const this_type(ContextT const&) >::type result_type;
  148. result_type strm = phoenix::eval(m_left, ctx);
  149. if (phoenix::eval(m_cond, ctx))
  150. phoenix::eval(m_then, ctx);
  151. else
  152. phoenix::eval(m_else, ctx);
  153. return strm;
  154. }
  155. BOOST_DELETED_FUNCTION(if_else_output_terminal())
  156. };
  157. template< typename CondT, typename ThenT, typename ElseT >
  158. struct if_then_else_gen
  159. {
  160. CondT m_cond;
  161. ThenT m_then;
  162. ElseT m_else;
  163. if_then_else_gen(CondT const& cond, ThenT const& then_, ElseT const& else_) : m_cond(cond), m_then(then_), m_else(else_)
  164. {
  165. }
  166. };
  167. #ifndef BOOST_LOG_DOXYGEN_PASS
  168. #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
  169. template< typename LeftExprT, typename CondT, typename ThenT, typename ElseT >\
  170. BOOST_FORCEINLINE phoenix::actor< if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > >\
  171. operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_else_gen< CondT, ThenT, ElseT > right_ref right)\
  172. {\
  173. typedef if_else_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT, ElseT > terminal_type;\
  174. phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.m_cond, right.m_then, right.m_else) }};\
  175. return actor;\
  176. }
  177. #include <boost/log/detail/generate_overloads.hpp>
  178. #undef BOOST_LOG_AUX_OVERLOAD
  179. #endif // BOOST_LOG_DOXYGEN_PASS
  180. template< typename CondT, typename ThenT >
  181. struct if_then_gen
  182. {
  183. struct else_gen
  184. {
  185. CondT m_cond;
  186. ThenT m_then;
  187. else_gen(CondT const& cond, ThenT const& then_) : m_cond(cond), m_then(then_)
  188. {
  189. }
  190. template< typename ElseT >
  191. BOOST_FORCEINLINE if_then_else_gen< CondT, ThenT, ElseT > operator[] (ElseT const& el)
  192. {
  193. return if_then_else_gen< CondT, ThenT, ElseT >(m_cond, m_then, el);
  194. }
  195. }
  196. else_;
  197. if_then_gen(CondT const& cond, ThenT const& then_) : else_(cond, then_) {}
  198. };
  199. #ifndef BOOST_LOG_DOXYGEN_PASS
  200. #define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\
  201. template< typename LeftExprT, typename CondT, typename ThenT >\
  202. BOOST_FORCEINLINE phoenix::actor< if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > >\
  203. operator<< (phoenix::actor< LeftExprT > left_ref left, if_then_gen< CondT, ThenT > right_ref right)\
  204. {\
  205. typedef if_output_terminal< phoenix::actor< LeftExprT >, CondT, ThenT > terminal_type;\
  206. phoenix::actor< terminal_type > actor = {{ terminal_type(left, right.else_.m_cond, right.else_.m_then) }};\
  207. return actor;\
  208. }
  209. #include <boost/log/detail/generate_overloads.hpp>
  210. #undef BOOST_LOG_AUX_OVERLOAD
  211. #endif // BOOST_LOG_DOXYGEN_PASS
  212. template< typename CondT >
  213. class if_gen
  214. {
  215. private:
  216. CondT const& m_cond;
  217. public:
  218. explicit if_gen(CondT const& cond) : m_cond(cond)
  219. {
  220. }
  221. template< typename ThenT >
  222. BOOST_FORCEINLINE if_then_gen< CondT, ThenT > operator[] (ThenT const& then_) const
  223. {
  224. return if_then_gen< CondT, ThenT >(m_cond, then_);
  225. }
  226. };
  227. } // namespace aux
  228. /*!
  229. * The function returns a conditional formatter generator object. The generator provides <tt>operator[]</tt> that can be used
  230. * to construct the actual formatter. The formatter must participate in a streaming expression.
  231. *
  232. * \param cond A filter expression that will be used as the condition
  233. */
  234. template< typename CondT >
  235. BOOST_FORCEINLINE aux::if_gen< CondT > if_(CondT const& cond)
  236. {
  237. return aux::if_gen< CondT >(cond);
  238. }
  239. } // namespace expressions
  240. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  241. #ifndef BOOST_LOG_DOXYGEN_PASS
  242. namespace phoenix {
  243. namespace result_of {
  244. template< typename LeftT, typename CondT, typename ThenT >
  245. struct is_nullary< custom_terminal< boost::log::expressions::aux::if_output_terminal< LeftT, CondT, ThenT > > > :
  246. public mpl::false_
  247. {
  248. };
  249. template< typename LeftT, typename CondT, typename ThenT, typename ElseT >
  250. struct is_nullary< custom_terminal< boost::log::expressions::aux::if_else_output_terminal< LeftT, CondT, ThenT, ElseT > > > :
  251. public mpl::false_
  252. {
  253. };
  254. } // namespace result_of
  255. } // namespace phoenix
  256. #endif
  257. } // namespace boost
  258. #include <boost/log/detail/footer.hpp>
  259. #endif // BOOST_LOG_EXPRESSIONS_FORMATTERS_IF_HPP_INCLUDED_