value_ref.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2013.
  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 value_ref.hpp
  9. * \author Andrey Semashev
  10. * \date 27.07.2012
  11. *
  12. * The header contains implementation of a value reference wrapper.
  13. */
  14. #ifndef BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
  15. #define BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
  16. #include <cstddef>
  17. #include <iosfwd>
  18. #include <boost/assert.hpp>
  19. #include <boost/mpl/if.hpp>
  20. #include <boost/mpl/eval_if.hpp>
  21. #include <boost/mpl/is_sequence.hpp>
  22. #include <boost/mpl/front.hpp>
  23. #include <boost/mpl/size.hpp>
  24. #include <boost/mpl/int.hpp>
  25. #include <boost/mpl/and.hpp>
  26. #include <boost/mpl/identity.hpp>
  27. #include <boost/mpl/equal_to.hpp>
  28. #include <boost/mpl/contains.hpp>
  29. #include <boost/mpl/index_of.hpp>
  30. #include <boost/utility/addressof.hpp>
  31. #include <boost/utility/enable_if.hpp>
  32. #include <boost/optional/optional_fwd.hpp>
  33. #include <boost/type_traits/is_same.hpp>
  34. #include <boost/type_traits/is_void.hpp>
  35. #include <boost/log/detail/config.hpp>
  36. #include <boost/log/detail/parameter_tools.hpp>
  37. #include <boost/log/detail/value_ref_visitation.hpp>
  38. #include <boost/utility/explicit_operator_bool.hpp>
  39. #include <boost/log/utility/formatting_ostream_fwd.hpp>
  40. #include <boost/log/utility/functional/logical.hpp>
  41. #include <boost/log/utility/functional/bind.hpp>
  42. #include <boost/log/utility/functional/bind_output.hpp>
  43. #include <boost/log/utility/functional/bind_to_log.hpp>
  44. #include <boost/log/utility/manipulators/to_log.hpp>
  45. #include <boost/log/utility/value_ref_fwd.hpp>
  46. #include <boost/log/detail/header.hpp>
  47. #ifdef BOOST_HAS_PRAGMA_ONCE
  48. #pragma once
  49. #endif
  50. namespace boost {
  51. BOOST_LOG_OPEN_NAMESPACE
  52. namespace aux {
  53. //! The function object applies the function object to the bound visitable object and argument
  54. template< typename VisitableT, typename FunT >
  55. struct vistation_invoker
  56. {
  57. typedef typename FunT::result_type result_type;
  58. vistation_invoker(VisitableT& visitable, result_type const& def_val) : m_visitable(visitable), m_def_val(def_val)
  59. {
  60. }
  61. template< typename ArgT >
  62. result_type operator() (ArgT const& arg) const
  63. {
  64. return m_visitable.apply_visitor_or_default(binder1st< FunT, ArgT const& >(FunT(), arg), m_def_val);
  65. }
  66. private:
  67. VisitableT& m_visitable;
  68. result_type m_def_val;
  69. };
  70. //! Attribute value reference implementation for a single type case
  71. template< typename T, typename TagT >
  72. class singular_ref
  73. {
  74. public:
  75. //! Referenced value type
  76. typedef T value_type;
  77. //! Tag type
  78. typedef TagT tag_type;
  79. protected:
  80. //! The metafunction tests if the type is compatible with the reference wrapper
  81. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  82. template< typename U >
  83. using is_compatible = is_same< U, value_type >;
  84. #else
  85. template< typename U >
  86. struct is_compatible :
  87. public is_same< U, value_type >
  88. {
  89. };
  90. #endif
  91. protected:
  92. //! Pointer to the value
  93. const value_type* m_ptr;
  94. protected:
  95. //! Default constructor
  96. singular_ref() BOOST_NOEXCEPT : m_ptr(NULL)
  97. {
  98. }
  99. //! Initializing constructor
  100. explicit singular_ref(const value_type* p) BOOST_NOEXCEPT : m_ptr(p)
  101. {
  102. }
  103. public:
  104. //! Returns a pointer to the referred value
  105. const value_type* operator-> () const BOOST_NOEXCEPT
  106. {
  107. BOOST_ASSERT(m_ptr != NULL);
  108. return m_ptr;
  109. }
  110. //! Returns a pointer to the referred value
  111. const value_type* get_ptr() const BOOST_NOEXCEPT
  112. {
  113. return m_ptr;
  114. }
  115. //! Returns a pointer to the referred value
  116. template< typename U >
  117. typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT
  118. {
  119. return m_ptr;
  120. }
  121. //! Returns a reference to the value
  122. value_type const& operator* () const BOOST_NOEXCEPT
  123. {
  124. BOOST_ASSERT(m_ptr != NULL);
  125. return *m_ptr;
  126. }
  127. //! Returns a reference to the value
  128. value_type const& get() const BOOST_NOEXCEPT
  129. {
  130. BOOST_ASSERT(m_ptr != NULL);
  131. return *m_ptr;
  132. }
  133. //! Returns a reference to the value
  134. template< typename U >
  135. typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT
  136. {
  137. BOOST_ASSERT(m_ptr != NULL);
  138. return *m_ptr;
  139. }
  140. //! Resets the reference
  141. void reset() BOOST_NOEXCEPT
  142. {
  143. m_ptr = NULL;
  144. }
  145. //! Returns the stored type index
  146. static BOOST_CONSTEXPR unsigned int which()
  147. {
  148. return 0u;
  149. }
  150. //! Swaps two reference wrappers
  151. void swap(singular_ref& that) BOOST_NOEXCEPT
  152. {
  153. const void* p = m_ptr;
  154. m_ptr = that.m_ptr;
  155. that.m_ptr = p;
  156. }
  157. //! Applies a visitor function object to the referred value
  158. template< typename VisitorT >
  159. typename VisitorT::result_type apply_visitor(VisitorT visitor) const
  160. {
  161. BOOST_ASSERT(m_ptr != NULL);
  162. return visitor(*m_ptr);
  163. }
  164. //! Applies a visitor function object to the referred value
  165. template< typename VisitorT >
  166. typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const
  167. {
  168. if (m_ptr)
  169. {
  170. visitor(*m_ptr);
  171. return true;
  172. }
  173. else
  174. return false;
  175. }
  176. //! Applies a visitor function object to the referred value
  177. template< typename VisitorT >
  178. typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
  179. {
  180. typedef optional< typename VisitorT::result_type > result_type;
  181. if (m_ptr)
  182. return result_type(visitor(*m_ptr));
  183. else
  184. return result_type();
  185. }
  186. //! Applies a visitor function object to the referred value or returns a default value
  187. template< typename VisitorT, typename DefaultT >
  188. typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
  189. {
  190. if (m_ptr)
  191. return visitor(*m_ptr);
  192. else
  193. return def_val;
  194. }
  195. //! Applies a visitor function object to the referred value or returns a default value
  196. template< typename VisitorT, typename DefaultT >
  197. typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
  198. {
  199. if (m_ptr)
  200. return visitor(*m_ptr);
  201. else
  202. return def_val;
  203. }
  204. };
  205. //! Attribute value reference implementation for multiple types case
  206. template< typename T, typename TagT >
  207. class variant_ref
  208. {
  209. public:
  210. //! Referenced value type
  211. typedef T value_type;
  212. //! Tag type
  213. typedef TagT tag_type;
  214. protected:
  215. //! The metafunction tests if the type is compatible with the reference wrapper
  216. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  217. template< typename U >
  218. using is_compatible = mpl::contains< value_type, U >;
  219. #else
  220. template< typename U >
  221. struct is_compatible :
  222. public mpl::contains< value_type, U >
  223. {
  224. };
  225. #endif
  226. protected:
  227. //! Pointer to the value
  228. const void* m_ptr;
  229. //! Type index
  230. unsigned int m_type_idx;
  231. protected:
  232. //! Default constructor
  233. variant_ref() BOOST_NOEXCEPT : m_ptr(NULL), m_type_idx(0)
  234. {
  235. }
  236. //! Initializing constructor
  237. template< typename U >
  238. explicit variant_ref(const U* p) BOOST_NOEXCEPT : m_ptr(p), m_type_idx(mpl::index_of< value_type, U >::type::value)
  239. {
  240. }
  241. public:
  242. //! Resets the reference
  243. void reset() BOOST_NOEXCEPT
  244. {
  245. m_ptr = NULL;
  246. m_type_idx = 0;
  247. }
  248. //! Returns a pointer to the referred value
  249. template< typename U >
  250. typename enable_if< is_compatible< U >, const U* >::type get_ptr() const BOOST_NOEXCEPT
  251. {
  252. if (m_type_idx == static_cast< unsigned int >(mpl::index_of< value_type, U >::type::value))
  253. return static_cast< const U* >(m_ptr);
  254. else
  255. return NULL;
  256. }
  257. //! Returns a reference to the value
  258. template< typename U >
  259. typename enable_if< is_compatible< U >, U const& >::type get() const BOOST_NOEXCEPT
  260. {
  261. const U* const p = get_ptr< U >();
  262. BOOST_ASSERT(p != NULL);
  263. return *p;
  264. }
  265. //! Returns the stored type index
  266. unsigned int which() const BOOST_NOEXCEPT
  267. {
  268. return m_type_idx;
  269. }
  270. //! Swaps two reference wrappers
  271. void swap(variant_ref& that) BOOST_NOEXCEPT
  272. {
  273. const void* p = m_ptr;
  274. m_ptr = that.m_ptr;
  275. that.m_ptr = p;
  276. unsigned int type_idx = m_type_idx;
  277. m_type_idx = that.m_type_idx;
  278. that.m_type_idx = type_idx;
  279. }
  280. //! Applies a visitor function object to the referred value
  281. template< typename VisitorT >
  282. typename VisitorT::result_type apply_visitor(VisitorT visitor) const
  283. {
  284. BOOST_ASSERT(m_ptr != NULL);
  285. return do_apply_visitor(visitor);
  286. }
  287. //! Applies a visitor function object to the referred value
  288. template< typename VisitorT >
  289. typename enable_if< is_void< typename VisitorT::result_type >, bool >::type apply_visitor_optional(VisitorT visitor) const
  290. {
  291. if (m_ptr)
  292. {
  293. do_apply_visitor(visitor);
  294. return true;
  295. }
  296. else
  297. return false;
  298. }
  299. //! Applies a visitor function object to the referred value
  300. template< typename VisitorT >
  301. typename disable_if< is_void< typename VisitorT::result_type >, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
  302. {
  303. typedef optional< typename VisitorT::result_type > result_type;
  304. if (m_ptr)
  305. return result_type(do_apply_visitor(visitor));
  306. else
  307. return result_type();
  308. }
  309. //! Applies a visitor function object to the referred value or returns a default value
  310. template< typename VisitorT, typename DefaultT >
  311. typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
  312. {
  313. if (m_ptr)
  314. return do_apply_visitor(visitor);
  315. else
  316. return def_val;
  317. }
  318. //! Applies a visitor function object to the referred value or returns a default value
  319. template< typename VisitorT, typename DefaultT >
  320. typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
  321. {
  322. if (m_ptr)
  323. return do_apply_visitor(visitor);
  324. else
  325. return def_val;
  326. }
  327. private:
  328. template< typename VisitorT >
  329. typename VisitorT::result_type do_apply_visitor(VisitorT& visitor) const
  330. {
  331. BOOST_ASSERT(m_type_idx < static_cast< unsigned int >(mpl::size< value_type >::value));
  332. return apply_visitor_dispatch< value_type, VisitorT >::call(m_ptr, m_type_idx, visitor);
  333. }
  334. };
  335. template< typename T, typename TagT >
  336. struct value_ref_base
  337. {
  338. typedef typename mpl::eval_if<
  339. mpl::and_< mpl::is_sequence< T >, mpl::equal_to< mpl::size< T >, mpl::int_< 1 > > >,
  340. mpl::front< T >,
  341. mpl::identity< T >
  342. >::type value_type;
  343. typedef typename mpl::if_<
  344. mpl::is_sequence< value_type >,
  345. variant_ref< value_type, TagT >,
  346. singular_ref< value_type, TagT >
  347. >::type type;
  348. };
  349. } // namespace aux
  350. /*!
  351. * \brief Reference wrapper for a stored attribute value.
  352. *
  353. * The \c value_ref class template provides access to the stored attribute value. It is not a traditional reference wrapper
  354. * since it may be empty (i.e. refer to no value at all) and it can also refer to values of different types. Therefore its
  355. * interface and behavior combines features of Boost.Ref, Boost.Optional and Boost.Variant, depending on the use case.
  356. *
  357. * The template parameter \c T can be a single type or an MPL sequence of possible types being referred. The reference wrapper
  358. * will act as either an optional reference or an optional variant of references to the specified types. In any case, the
  359. * referred values will not be modifiable (i.e. \c value_ref always models a const reference).
  360. *
  361. * Template parameter \c TagT is optional. It can be used for customizing the operations on this reference wrapper, such as
  362. * putting the referred value to log.
  363. */
  364. template< typename T, typename TagT >
  365. class value_ref :
  366. public aux::value_ref_base< T, TagT >::type
  367. {
  368. #ifndef BOOST_LOG_DOXYGEN_PASS
  369. public:
  370. typedef void _has_basic_formatting_ostream_insert_operator;
  371. #endif
  372. private:
  373. //! Base implementation type
  374. typedef typename aux::value_ref_base< T, TagT >::type base_type;
  375. public:
  376. /*!
  377. * Default constructor. Creates a reference wrapper that does not refer to a value.
  378. */
  379. BOOST_DEFAULTED_FUNCTION(value_ref(), BOOST_NOEXCEPT {})
  380. /*!
  381. * Copy constructor.
  382. */
  383. BOOST_DEFAULTED_FUNCTION(value_ref(value_ref const& that), BOOST_NOEXCEPT : base_type(static_cast< base_type const& >(that)) {})
  384. /*!
  385. * Initializing constructor. Creates a reference wrapper that refers to the specified value.
  386. */
  387. template< typename U >
  388. explicit value_ref(U const& val, typename enable_if< typename base_type::BOOST_NESTED_TEMPLATE is_compatible< U >, int >::type = 0) BOOST_NOEXCEPT :
  389. base_type(boost::addressof(val))
  390. {
  391. }
  392. /*!
  393. * The operator verifies if the wrapper refers to a value.
  394. */
  395. BOOST_EXPLICIT_OPERATOR_BOOL()
  396. /*!
  397. * The operator verifies if the wrapper does not refer to a value.
  398. */
  399. bool operator! () const BOOST_NOEXCEPT
  400. {
  401. return !this->m_ptr;
  402. }
  403. /*!
  404. * \return \c true if the wrapper does not refer to a value.
  405. */
  406. bool empty() const BOOST_NOEXCEPT
  407. {
  408. return !this->m_ptr;
  409. }
  410. /*!
  411. * Swaps two reference wrappers
  412. */
  413. void swap(value_ref& that) BOOST_NOEXCEPT
  414. {
  415. base_type::swap(that);
  416. }
  417. };
  418. //! Free swap function
  419. template< typename T, typename TagT >
  420. inline void swap(value_ref< T, TagT >& left, value_ref< T, TagT >& right)
  421. {
  422. left.swap(right);
  423. }
  424. //! Stream output operator
  425. template< typename CharT, typename TraitsT, typename T, typename TagT >
  426. inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, value_ref< T, TagT > const& val)
  427. {
  428. if (!!val)
  429. val.apply_visitor(boost::log::bind_output(strm));
  430. return strm;
  431. }
  432. //! Log formatting operator
  433. template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT >
  434. inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, value_ref< T, TagT > const& val)
  435. {
  436. if (!!val)
  437. val.apply_visitor(boost::log::bind_to_log< TagT >(strm));
  438. return strm;
  439. }
  440. // Equality comparison
  441. template< typename T, typename TagT, typename U >
  442. inline bool operator== (value_ref< T, TagT > const& left, U const& right)
  443. {
  444. return left.apply_visitor_or_default(binder2nd< equal_to, U const& >(equal_to(), right), false);
  445. }
  446. template< typename U, typename T, typename TagT >
  447. inline bool operator== (U const& left, value_ref< T, TagT > const& right)
  448. {
  449. return right.apply_visitor_or_default(binder1st< equal_to, U const& >(equal_to(), left), false);
  450. }
  451. template< typename T1, typename TagT1, typename T2, typename TagT2 >
  452. inline bool operator== (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
  453. {
  454. if (!left && !right)
  455. return true;
  456. return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, equal_to >(right, false), false);
  457. }
  458. // Inequality comparison
  459. template< typename T, typename TagT, typename U >
  460. inline bool operator!= (value_ref< T, TagT > const& left, U const& right)
  461. {
  462. return left.apply_visitor_or_default(binder2nd< not_equal_to, U const& >(not_equal_to(), right), false);
  463. }
  464. template< typename U, typename T, typename TagT >
  465. inline bool operator!= (U const& left, value_ref< T, TagT > const& right)
  466. {
  467. return right.apply_visitor_or_default(binder1st< not_equal_to, U const& >(not_equal_to(), left), false);
  468. }
  469. template< typename T1, typename TagT1, typename T2, typename TagT2 >
  470. inline bool operator!= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
  471. {
  472. if (!left && !right)
  473. return false;
  474. return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, not_equal_to >(right, false), false);
  475. }
  476. // Less than ordering
  477. template< typename T, typename TagT, typename U >
  478. inline bool operator< (value_ref< T, TagT > const& left, U const& right)
  479. {
  480. return left.apply_visitor_or_default(binder2nd< less, U const& >(less(), right), false);
  481. }
  482. template< typename U, typename T, typename TagT >
  483. inline bool operator< (U const& left, value_ref< T, TagT > const& right)
  484. {
  485. return right.apply_visitor_or_default(binder1st< less, U const& >(less(), left), false);
  486. }
  487. template< typename T1, typename TagT1, typename T2, typename TagT2 >
  488. inline bool operator< (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
  489. {
  490. return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less >(right, false), false);
  491. }
  492. // Greater than ordering
  493. template< typename T, typename TagT, typename U >
  494. inline bool operator> (value_ref< T, TagT > const& left, U const& right)
  495. {
  496. return left.apply_visitor_or_default(binder2nd< greater, U const& >(greater(), right), false);
  497. }
  498. template< typename U, typename T, typename TagT >
  499. inline bool operator> (U const& left, value_ref< T, TagT > const& right)
  500. {
  501. return right.apply_visitor_or_default(binder1st< greater, U const& >(greater(), left), false);
  502. }
  503. template< typename T1, typename TagT1, typename T2, typename TagT2 >
  504. inline bool operator> (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
  505. {
  506. return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater >(right, false), false);
  507. }
  508. // Less or equal ordering
  509. template< typename T, typename TagT, typename U >
  510. inline bool operator<= (value_ref< T, TagT > const& left, U const& right)
  511. {
  512. return left.apply_visitor_or_default(binder2nd< less_equal, U const& >(less_equal(), right), false);
  513. }
  514. template< typename U, typename T, typename TagT >
  515. inline bool operator<= (U const& left, value_ref< T, TagT > const& right)
  516. {
  517. return right.apply_visitor_or_default(binder1st< less_equal, U const& >(less_equal(), left), false);
  518. }
  519. template< typename T1, typename TagT1, typename T2, typename TagT2 >
  520. inline bool operator<= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
  521. {
  522. if (!left && !right)
  523. return true;
  524. return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less_equal >(right, false), false);
  525. }
  526. // Greater or equal ordering
  527. template< typename T, typename TagT, typename U >
  528. inline bool operator>= (value_ref< T, TagT > const& left, U const& right)
  529. {
  530. return left.apply_visitor_or_default(binder2nd< greater_equal, U const& >(greater_equal(), right), false);
  531. }
  532. template< typename U, typename T, typename TagT >
  533. inline bool operator>= (U const& left, value_ref< T, TagT > const& right)
  534. {
  535. return right.apply_visitor_or_default(binder1st< greater_equal, U const& >(greater_equal(), left), false);
  536. }
  537. template< typename T1, typename TagT1, typename T2, typename TagT2 >
  538. inline bool operator>= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
  539. {
  540. if (!left && !right)
  541. return true;
  542. return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater_equal >(right, false), false);
  543. }
  544. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  545. } // namespace boost
  546. #include <boost/log/detail/footer.hpp>
  547. #endif // BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_