value_ref.hpp 21 KB

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