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