]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/log/include/boost/log/utility/value_ref.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / log / include / boost / log / utility / value_ref.hpp
CommitLineData
7c673cae
FG
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
53namespace boost {
54
55BOOST_LOG_OPEN_NAMESPACE
56
57namespace aux {
58
59//! The function object applies the function object to the bound visitable object and argument
60template< typename VisitableT, typename FunT >
61struct vistation_invoker
62{
63 typedef typename FunT::result_type result_type;
64
65 vistation_invoker(VisitableT& visitable, result_type const& def_val) : m_visitable(visitable), m_def_val(def_val)
66 {
67 }
68
69 template< typename ArgT >
70 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
75private:
76 VisitableT& m_visitable;
77 result_type m_def_val;
78};
79
80//! Traits for testing type compatibility with the reference wrapper
81struct 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
96template< typename T, typename TagT >
97class singular_ref
98{
99public:
100 //! Referenced value type
101 typedef T value_type;
102 //! Tag type
103 typedef TagT tag_type;
104
105protected:
106 //! Traits for testing type compatibility with the reference wrapper
107 typedef singular_ref_compatibility_traits compatibility_traits;
108
109protected:
110 //! Pointer to the value
111 const value_type* m_ptr;
112
113protected:
114 //! Default constructor
115 singular_ref() BOOST_NOEXCEPT : m_ptr(NULL)
116 {
117 }
118
119 //! Initializing constructor
120 explicit singular_ref(const value_type* p) BOOST_NOEXCEPT : m_ptr(p)
121 {
122 }
123
124public:
125 //! Returns a pointer to the referred value
126 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
133 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 >
140 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
146 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
153 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 >
161 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
169 void reset() BOOST_NOEXCEPT
170 {
171 m_ptr = NULL;
172 }
173
174 //! Returns the stored type index
175 static BOOST_CONSTEXPR unsigned int which()
176 {
177 return 0u;
178 }
179
180 //! Swaps two reference wrappers
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 >
190 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 >
198 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 >
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
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 >
222 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 >
232 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
242struct 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
252template< typename T, typename TagT >
253class variant_ref
254{
255public:
256 //! Referenced value type
257 typedef T value_type;
258 //! Tag type
259 typedef TagT tag_type;
260
261protected:
262 //! Traits for testing type compatibility with the reference wrapper
263 typedef variant_ref_compatibility_traits compatibility_traits;
264
265protected:
266 //! Pointer to the value
267 const void* m_ptr;
268 //! Type index
269 unsigned int m_type_idx;
270
271protected:
272 //! Default constructor
273 variant_ref() BOOST_NOEXCEPT : m_ptr(NULL), m_type_idx(0)
274 {
275 }
276
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)
280 {
281 }
282
283public:
284 //! Resets the reference
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 >
293 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 >
303 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
311 unsigned int which() const BOOST_NOEXCEPT
312 {
313 return m_type_idx;
314 }
315
316 //! Swaps two reference wrappers
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 >
329 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 >
337 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 >
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
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 >
361 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 >
371 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
379private:
380 template< typename VisitorT >
381 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
388template< typename T, typename TagT >
389struct 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 */
420template< typename T, typename TagT >
421class value_ref :
422 public aux::value_ref_base< T, TagT >::type
423{
424#ifndef BOOST_LOG_DOXYGEN_PASS
425public:
426 typedef void _has_basic_formatting_ostream_insert_operator;
427#endif
428
429private:
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
435public:
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
446public:
447 /*!
448 * Default constructor. Creates a reference wrapper that does not refer to a value.
449 */
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 */
489 bool empty() const BOOST_NOEXCEPT
490 {
491 return !this->m_ptr;
492 }
493
494 /*!
495 * Swaps two reference wrappers
496 */
497 void swap(value_ref& that) BOOST_NOEXCEPT
498 {
499 base_type::swap(that);
500 }
501};
502
503//! Free swap function
504template< typename T, typename TagT >
505inline void swap(value_ref< T, TagT >& left, value_ref< T, TagT >& right)
506{
507 left.swap(right);
508}
509
510//! Stream output operator
511template< typename CharT, typename TraitsT, typename T, typename TagT >
512inline 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
520template< typename CharT, typename TraitsT, typename AllocatorT, typename T, typename TagT >
521inline 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
529template< typename T, typename TagT, typename U >
530inline 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
535template< typename U, typename T, typename TagT >
536inline 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
541template< typename T1, typename TagT1, typename T2, typename TagT2 >
542inline 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
550template< typename T, typename TagT, typename U >
551inline 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
556template< typename U, typename T, typename TagT >
557inline 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
562template< typename T1, typename TagT1, typename T2, typename TagT2 >
563inline 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
571template< typename T, typename TagT, typename U >
572inline 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
577template< typename U, typename T, typename TagT >
578inline 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
583template< typename T1, typename TagT1, typename T2, typename TagT2 >
584inline 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
590template< typename T, typename TagT, typename U >
591inline 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
596template< typename U, typename T, typename TagT >
597inline 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
602template< typename T1, typename TagT1, typename T2, typename TagT2 >
603inline 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
609template< typename T, typename TagT, typename U >
610inline 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
615template< typename U, typename T, typename TagT >
616inline 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
621template< typename T1, typename TagT1, typename T2, typename TagT2 >
622inline 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
630template< typename T, typename TagT, typename U >
631inline 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
636template< typename U, typename T, typename TagT >
637inline 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
642template< typename T1, typename TagT1, typename T2, typename TagT2 >
643inline 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
650BOOST_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_