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