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)
9 * \author Andrey Semashev
12 * The header contains implementation of a value reference wrapper.
15 #ifndef BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
16 #define BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_
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>
49 #ifdef BOOST_HAS_PRAGMA_ONCE
55 BOOST_LOG_OPEN_NAMESPACE
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
63 typedef typename FunT::result_type result_type;
65 vistation_invoker(VisitableT& visitable, result_type const& def_val) : m_visitable(visitable), m_def_val(def_val)
69 template< typename ArgT >
70 result_type operator() (ArgT const& arg) const
72 return m_visitable.apply_visitor_or_default(binder1st< FunT, ArgT const& >(FunT(), arg), m_def_val);
76 VisitableT& m_visitable;
77 result_type m_def_val;
80 //! Traits for testing type compatibility with the reference wrapper
81 struct singular_ref_compatibility_traits
83 template< typename T, typename U >
86 BOOST_STATIC_CONSTANT(bool, value = false);
88 template< typename T >
89 struct is_compatible< T, T >
91 BOOST_STATIC_CONSTANT(bool, value = true);
95 //! Attribute value reference implementation for a single type case
96 template< typename T, typename TagT >
100 //! Referenced value type
101 typedef T value_type;
103 typedef TagT tag_type;
106 //! Traits for testing type compatibility with the reference wrapper
107 typedef singular_ref_compatibility_traits compatibility_traits;
110 //! Pointer to the value
111 const value_type* m_ptr;
114 //! Default constructor
115 singular_ref() BOOST_NOEXCEPT : m_ptr(NULL)
119 //! Initializing constructor
120 explicit singular_ref(const value_type* p) BOOST_NOEXCEPT : m_ptr(p)
125 //! Returns a pointer to the referred value
126 const value_type* operator-> () const BOOST_NOEXCEPT
128 BOOST_ASSERT(m_ptr != NULL);
132 //! Returns a pointer to the referred value
133 const value_type* get_ptr() const BOOST_NOEXCEPT
138 //! Returns a pointer to the referred value
139 template< typename U >
140 typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, const U* >::type get_ptr() const BOOST_NOEXCEPT
145 //! Returns a reference to the value
146 value_type const& operator* () const BOOST_NOEXCEPT
148 BOOST_ASSERT(m_ptr != NULL);
152 //! Returns a reference to the value
153 value_type const& get() const BOOST_NOEXCEPT
155 BOOST_ASSERT(m_ptr != NULL);
159 //! Returns a reference to the value
160 template< typename U >
161 typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, U const& >::type get() const BOOST_NOEXCEPT
163 BOOST_ASSERT(m_ptr != NULL);
168 //! Resets the reference
169 void reset() BOOST_NOEXCEPT
174 //! Returns the stored type index
175 static BOOST_CONSTEXPR unsigned int which()
180 //! Swaps two reference wrappers
181 void swap(singular_ref& that) BOOST_NOEXCEPT
183 const void* p = m_ptr;
188 //! Applies a visitor function object to the referred value
189 template< typename VisitorT >
190 typename VisitorT::result_type apply_visitor(VisitorT visitor) const
192 BOOST_ASSERT(m_ptr != NULL);
193 return visitor(*m_ptr);
196 //! Applies a visitor function object to the referred value
197 template< typename VisitorT >
198 typename boost::enable_if_c< is_void< typename VisitorT::result_type >::value, bool >::type apply_visitor_optional(VisitorT visitor) const
209 //! Applies a visitor function object to the referred value
210 template< typename VisitorT >
211 typename boost::disable_if_c< is_void< typename VisitorT::result_type >::value, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
213 typedef optional< typename VisitorT::result_type > result_type;
215 return result_type(visitor(*m_ptr));
217 return result_type();
220 //! Applies a visitor function object to the referred value or returns a default value
221 template< typename VisitorT, typename DefaultT >
222 typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
225 return visitor(*m_ptr);
230 //! Applies a visitor function object to the referred value or returns a default value
231 template< typename VisitorT, typename DefaultT >
232 typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
235 return visitor(*m_ptr);
241 //! Traits for testing type compatibility with the reference wrapper
242 struct variant_ref_compatibility_traits
244 template< typename T, typename U >
247 BOOST_STATIC_CONSTANT(bool, value = (mpl::contains< T, U >::type::value));
251 //! Attribute value reference implementation for multiple types case
252 template< typename T, typename TagT >
256 //! Referenced value type
257 typedef T value_type;
259 typedef TagT tag_type;
262 //! Traits for testing type compatibility with the reference wrapper
263 typedef variant_ref_compatibility_traits compatibility_traits;
266 //! Pointer to the value
269 unsigned int m_type_idx;
272 //! Default constructor
273 variant_ref() BOOST_NOEXCEPT : m_ptr(NULL), m_type_idx(0)
277 //! Initializing constructor
278 template< typename U >
279 explicit variant_ref(const U* p) BOOST_NOEXCEPT : m_ptr(p), m_type_idx(mpl::index_of< value_type, U >::type::value)
284 //! Resets the reference
285 void reset() BOOST_NOEXCEPT
291 //! Returns a pointer to the referred value
292 template< typename U >
293 typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, const U* >::type get_ptr() const BOOST_NOEXCEPT
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);
301 //! Returns a reference to the value
302 template< typename U >
303 typename boost::enable_if_c< compatibility_traits::is_compatible< value_type, U >::value, U const& >::type get() const BOOST_NOEXCEPT
305 const U* const p = get_ptr< U >();
306 BOOST_ASSERT(p != NULL);
310 //! Returns the stored type index
311 unsigned int which() const BOOST_NOEXCEPT
316 //! Swaps two reference wrappers
317 void swap(variant_ref& that) BOOST_NOEXCEPT
319 const void* p = m_ptr;
322 unsigned int type_idx = m_type_idx;
323 m_type_idx = that.m_type_idx;
324 that.m_type_idx = type_idx;
327 //! Applies a visitor function object to the referred value
328 template< typename VisitorT >
329 typename VisitorT::result_type apply_visitor(VisitorT visitor) const
331 BOOST_ASSERT(m_ptr != NULL);
332 return do_apply_visitor(visitor);
335 //! Applies a visitor function object to the referred value
336 template< typename VisitorT >
337 typename boost::enable_if_c< is_void< typename VisitorT::result_type >::value, bool >::type apply_visitor_optional(VisitorT visitor) const
341 do_apply_visitor(visitor);
348 //! Applies a visitor function object to the referred value
349 template< typename VisitorT >
350 typename boost::disable_if_c< is_void< typename VisitorT::result_type >::value, optional< typename VisitorT::result_type > >::type apply_visitor_optional(VisitorT visitor) const
352 typedef optional< typename VisitorT::result_type > result_type;
354 return result_type(do_apply_visitor(visitor));
356 return result_type();
359 //! Applies a visitor function object to the referred value or returns a default value
360 template< typename VisitorT, typename DefaultT >
361 typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT& def_val) const
364 return do_apply_visitor(visitor);
369 //! Applies a visitor function object to the referred value or returns a default value
370 template< typename VisitorT, typename DefaultT >
371 typename VisitorT::result_type apply_visitor_or_default(VisitorT visitor, DefaultT const& def_val) const
374 return do_apply_visitor(visitor);
380 template< typename VisitorT >
381 typename VisitorT::result_type do_apply_visitor(VisitorT& visitor) const
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);
388 template< typename T, typename TagT >
389 struct value_ref_base
391 typedef typename mpl::eval_if<
392 mpl::and_< mpl::is_sequence< T >, mpl::equal_to< mpl::size< T >, mpl::int_< 1 > > >,
397 typedef typename mpl::if_<
398 mpl::is_sequence< value_type >,
399 variant_ref< value_type, TagT >,
400 singular_ref< value_type, TagT >
407 * \brief Reference wrapper for a stored attribute value.
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.
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).
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.
420 template< typename T, typename TagT >
422 public aux::value_ref_base< T, TagT >::type
424 #ifndef BOOST_LOG_DOXYGEN_PASS
426 typedef void _has_basic_formatting_ostream_insert_operator;
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;
436 #ifndef BOOST_LOG_DOXYGEN_PASS
437 //! Referenced value type
438 typedef typename base_type::value_type value_type;
440 //! Referenced value type
441 typedef T value_type;
443 typedef TagT tag_type;
448 * Default constructor. Creates a reference wrapper that does not refer to a value.
450 BOOST_DEFAULTED_FUNCTION(value_ref(), BOOST_NOEXCEPT {})
455 BOOST_DEFAULTED_FUNCTION(value_ref(value_ref const& that), BOOST_NOEXCEPT : base_type(static_cast< base_type const& >(that)) {})
458 * Initializing constructor. Creates a reference wrapper that refers to the specified value.
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()
469 base_type(boost::addressof(val))
474 * The operator verifies if the wrapper refers to a value.
476 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
479 * The operator verifies if the wrapper does not refer to a value.
481 bool operator! () const BOOST_NOEXCEPT
487 * \return \c true if the wrapper does not refer to a value.
489 bool empty() const BOOST_NOEXCEPT
495 * Swaps two reference wrappers
497 void swap(value_ref& that) BOOST_NOEXCEPT
499 base_type::swap(that);
503 //! Free swap function
504 template< typename T, typename TagT >
505 inline void swap(value_ref< T, TagT >& left, value_ref< T, TagT >& right)
510 //! Stream output operator
511 template< typename CharT, typename TraitsT, typename T, typename TagT >
512 inline std::basic_ostream< CharT, TraitsT >& operator<< (std::basic_ostream< CharT, TraitsT >& strm, value_ref< T, TagT > const& val)
515 val.apply_visitor(boost::log::bind_output(strm));
519 //! Log formatting operator
520 template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT >
521 inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >& operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, value_ref< T, TagT > const& val)
524 val.apply_visitor(boost::log::bind_to_log< TagT >(strm));
528 // Equality comparison
529 template< typename T, typename TagT, typename U >
530 inline bool operator== (value_ref< T, TagT > const& left, U const& right)
532 return left.apply_visitor_or_default(binder2nd< equal_to, U const& >(equal_to(), right), false);
535 template< typename U, typename T, typename TagT >
536 inline bool operator== (U const& left, value_ref< T, TagT > const& right)
538 return right.apply_visitor_or_default(binder1st< equal_to, U const& >(equal_to(), left), false);
541 template< typename T1, typename TagT1, typename T2, typename TagT2 >
542 inline bool operator== (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
546 return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, equal_to >(right, false), false);
549 // Inequality comparison
550 template< typename T, typename TagT, typename U >
551 inline bool operator!= (value_ref< T, TagT > const& left, U const& right)
553 return left.apply_visitor_or_default(binder2nd< not_equal_to, U const& >(not_equal_to(), right), false);
556 template< typename U, typename T, typename TagT >
557 inline bool operator!= (U const& left, value_ref< T, TagT > const& right)
559 return right.apply_visitor_or_default(binder1st< not_equal_to, U const& >(not_equal_to(), left), false);
562 template< typename T1, typename TagT1, typename T2, typename TagT2 >
563 inline bool operator!= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
567 return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, not_equal_to >(right, false), false);
570 // Less than ordering
571 template< typename T, typename TagT, typename U >
572 inline bool operator< (value_ref< T, TagT > const& left, U const& right)
574 return left.apply_visitor_or_default(binder2nd< less, U const& >(less(), right), false);
577 template< typename U, typename T, typename TagT >
578 inline bool operator< (U const& left, value_ref< T, TagT > const& right)
580 return right.apply_visitor_or_default(binder1st< less, U const& >(less(), left), false);
583 template< typename T1, typename TagT1, typename T2, typename TagT2 >
584 inline bool operator< (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
586 return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less >(right, false), false);
589 // Greater than ordering
590 template< typename T, typename TagT, typename U >
591 inline bool operator> (value_ref< T, TagT > const& left, U const& right)
593 return left.apply_visitor_or_default(binder2nd< greater, U const& >(greater(), right), false);
596 template< typename U, typename T, typename TagT >
597 inline bool operator> (U const& left, value_ref< T, TagT > const& right)
599 return right.apply_visitor_or_default(binder1st< greater, U const& >(greater(), left), false);
602 template< typename T1, typename TagT1, typename T2, typename TagT2 >
603 inline bool operator> (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
605 return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater >(right, false), false);
608 // Less or equal ordering
609 template< typename T, typename TagT, typename U >
610 inline bool operator<= (value_ref< T, TagT > const& left, U const& right)
612 return left.apply_visitor_or_default(binder2nd< less_equal, U const& >(less_equal(), right), false);
615 template< typename U, typename T, typename TagT >
616 inline bool operator<= (U const& left, value_ref< T, TagT > const& right)
618 return right.apply_visitor_or_default(binder1st< less_equal, U const& >(less_equal(), left), false);
621 template< typename T1, typename TagT1, typename T2, typename TagT2 >
622 inline bool operator<= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
626 return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, less_equal >(right, false), false);
629 // Greater or equal ordering
630 template< typename T, typename TagT, typename U >
631 inline bool operator>= (value_ref< T, TagT > const& left, U const& right)
633 return left.apply_visitor_or_default(binder2nd< greater_equal, U const& >(greater_equal(), right), false);
636 template< typename U, typename T, typename TagT >
637 inline bool operator>= (U const& left, value_ref< T, TagT > const& right)
639 return right.apply_visitor_or_default(binder1st< greater_equal, U const& >(greater_equal(), left), false);
642 template< typename T1, typename TagT1, typename T2, typename TagT2 >
643 inline bool operator>= (value_ref< T1, TagT1 > const& left, value_ref< T2, TagT2 > const& right)
647 return left.apply_visitor_or_default(aux::vistation_invoker< value_ref< T2, TagT2 >, greater_equal >(right, false), false);
650 BOOST_LOG_CLOSE_NAMESPACE // namespace log
654 #include <boost/log/detail/footer.hpp>
656 #endif // BOOST_LOG_UTILITY_VALUE_REF_HPP_INCLUDED_