]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentracing-cpp/3rd_party/include/opentracing/variant/variant.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / opentracing-cpp / 3rd_party / include / opentracing / variant / variant.hpp
1 #ifndef OPENTRACING_UTIL_VARIANT_HPP
2 #define OPENTRACING_UTIL_VARIANT_HPP
3
4 #include <cassert>
5 #include <cstddef> // size_t
6 #include <new> // operator new
7 #include <stdexcept> // runtime_error
8 #include <string>
9 #include <tuple>
10 #include <type_traits>
11 #include <typeinfo>
12 #include <utility>
13 #include <opentracing/version.h>
14
15 #include "recursive_wrapper.hpp"
16
17 // clang-format off
18 // [[deprecated]] is only available in C++14, use this for the time being
19 #if __cplusplus <= 201103L
20 # ifdef __GNUC__
21 # define OPENTRACING_VARIANT_DEPRECATED __attribute__((deprecated))
22 # elif defined(_MSC_VER)
23 # define OPENTRACING_VARIANT_DEPRECATED __declspec(deprecated)
24 # else
25 # define OPENTRACING_VARIANT_DEPRECATED
26 # endif
27 #else
28 # define OPENTRACING_VARIANT_DEPRECATED [[deprecated]]
29 #endif
30
31
32 #ifdef _MSC_VER
33 // https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx
34 #ifdef NDEBUG
35 #define VARIANT_INLINE __forceinline
36 #else
37 #define VARIANT_INLINE __declspec(noinline)
38 #endif
39 #else
40 #ifdef NDEBUG
41 #define VARIANT_INLINE inline __attribute__((always_inline))
42 #else
43 #define VARIANT_INLINE __attribute__((noinline))
44 #endif
45 #endif
46 // clang-format on
47
48 #define VARIANT_MAJOR_VERSION 1
49 #define VARIANT_MINOR_VERSION 1
50 #define VARIANT_PATCH_VERSION 0
51
52 #define VARIANT_VERSION (VARIANT_MAJOR_VERSION * 100000) + (VARIANT_MINOR_VERSION * 100) + (VARIANT_PATCH_VERSION)
53
54 namespace opentracing {
55 BEGIN_OPENTRACING_ABI_NAMESPACE
56 namespace util {
57
58 // XXX This should derive from std::logic_error instead of std::runtime_error.
59 // See https://github.com/opentracing/variant/issues/48 for details.
60 class bad_variant_access : public std::runtime_error
61 {
62
63 public:
64 explicit bad_variant_access(const std::string& what_arg)
65 : runtime_error(what_arg) {}
66
67 explicit bad_variant_access(const char* what_arg)
68 : runtime_error(what_arg) {}
69
70 }; // class bad_variant_access
71
72 template <typename R = void>
73 struct OPENTRACING_VARIANT_DEPRECATED static_visitor
74 {
75 using result_type = R;
76
77 protected:
78 static_visitor() {}
79 ~static_visitor() {}
80 };
81
82 namespace detail {
83
84 static constexpr std::size_t invalid_value = std::size_t(-1);
85
86 template <typename T, typename... Types>
87 struct direct_type;
88
89 template <typename T, typename First, typename... Types>
90 struct direct_type<T, First, Types...>
91 {
92 static constexpr std::size_t index = std::is_same<T, First>::value
93 ? sizeof...(Types)
94 : direct_type<T, Types...>::index;
95 };
96
97 template <typename T>
98 struct direct_type<T>
99 {
100 static constexpr std::size_t index = invalid_value;
101 };
102
103 template <typename T, typename... Types>
104 struct convertible_type;
105
106 template <typename T, typename First, typename... Types>
107 struct convertible_type<T, First, Types...>
108 {
109 static constexpr std::size_t index = std::is_convertible<T, First>::value
110 ? sizeof...(Types)
111 : convertible_type<T, Types...>::index;
112 };
113
114 template <typename T>
115 struct convertible_type<T>
116 {
117 static constexpr std::size_t index = invalid_value;
118 };
119
120 template <typename T, typename... Types>
121 struct value_traits
122 {
123 using value_type = typename std::remove_reference<T>::type;
124 static constexpr std::size_t direct_index = direct_type<value_type, Types...>::index;
125 static constexpr bool is_direct = direct_index != invalid_value;
126 static constexpr std::size_t index = is_direct ? direct_index : convertible_type<value_type, Types...>::index;
127 static constexpr bool is_valid = index != invalid_value;
128 static constexpr std::size_t tindex = is_valid ? sizeof...(Types)-index : 0;
129 using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
130 };
131
132 // check if T is in Types...
133 template <typename T, typename... Types>
134 struct has_type;
135
136 template <typename T, typename First, typename... Types>
137 struct has_type<T, First, Types...>
138 {
139 static constexpr bool value = std::is_same<T, First>::value || has_type<T, Types...>::value;
140 };
141
142 template <typename T>
143 struct has_type<T> : std::false_type
144 {
145 };
146
147 template <typename T, typename... Types>
148 struct is_valid_type;
149
150 template <typename T, typename First, typename... Types>
151 struct is_valid_type<T, First, Types...>
152 {
153 static constexpr bool value = std::is_convertible<T, First>::value || is_valid_type<T, Types...>::value;
154 };
155
156 template <typename T>
157 struct is_valid_type<T> : std::false_type
158 {
159 };
160
161 template <typename T, typename R = void>
162 struct enable_if_type
163 {
164 using type = R;
165 };
166
167 template <typename F, typename V, typename Enable = void>
168 struct result_of_unary_visit
169 {
170 using type = typename std::result_of<F(V&)>::type;
171 };
172
173 template <typename F, typename V>
174 struct result_of_unary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
175 {
176 using type = typename F::result_type;
177 };
178
179 template <typename F, typename V, typename Enable = void>
180 struct result_of_binary_visit
181 {
182 using type = typename std::result_of<F(V&, V&)>::type;
183 };
184
185 template <typename F, typename V>
186 struct result_of_binary_visit<F, V, typename enable_if_type<typename F::result_type>::type>
187 {
188 using type = typename F::result_type;
189 };
190
191 template <std::size_t arg1, std::size_t... others>
192 struct static_max;
193
194 template <std::size_t arg>
195 struct static_max<arg>
196 {
197 static const std::size_t value = arg;
198 };
199
200 template <std::size_t arg1, std::size_t arg2, std::size_t... others>
201 struct static_max<arg1, arg2, others...>
202 {
203 static const std::size_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
204 };
205
206 template <typename... Types>
207 struct variant_helper;
208
209 template <typename T, typename... Types>
210 struct variant_helper<T, Types...>
211 {
212 VARIANT_INLINE static void destroy(const std::size_t type_index, void* data)
213 {
214 if (type_index == sizeof...(Types))
215 {
216 reinterpret_cast<T*>(data)->~T();
217 }
218 else
219 {
220 variant_helper<Types...>::destroy(type_index, data);
221 }
222 }
223
224 VARIANT_INLINE static void move(const std::size_t old_type_index, void* old_value, void* new_value)
225 {
226 if (old_type_index == sizeof...(Types))
227 {
228 new (new_value) T(std::move(*reinterpret_cast<T*>(old_value)));
229 }
230 else
231 {
232 variant_helper<Types...>::move(old_type_index, old_value, new_value);
233 }
234 }
235
236 VARIANT_INLINE static void copy(const std::size_t old_type_index, const void* old_value, void* new_value)
237 {
238 if (old_type_index == sizeof...(Types))
239 {
240 new (new_value) T(*reinterpret_cast<const T*>(old_value));
241 }
242 else
243 {
244 variant_helper<Types...>::copy(old_type_index, old_value, new_value);
245 }
246 }
247 };
248
249 template <>
250 struct variant_helper<>
251 {
252 VARIANT_INLINE static void destroy(const std::size_t, void*) {}
253 VARIANT_INLINE static void move(const std::size_t, void*, void*) {}
254 VARIANT_INLINE static void copy(const std::size_t, const void*, void*) {}
255 };
256
257 template <typename T>
258 struct unwrapper
259 {
260 static T const& apply_const(T const& obj) { return obj; }
261 static T& apply(T& obj) { return obj; }
262 };
263
264 template <typename T>
265 struct unwrapper<recursive_wrapper<T>>
266 {
267 static auto apply_const(recursive_wrapper<T> const& obj)
268 -> typename recursive_wrapper<T>::type const&
269 {
270 return obj.get();
271 }
272 static auto apply(recursive_wrapper<T>& obj)
273 -> typename recursive_wrapper<T>::type&
274 {
275 return obj.get();
276 }
277 };
278
279 template <typename T>
280 struct unwrapper<std::reference_wrapper<T>>
281 {
282 static auto apply_const(std::reference_wrapper<T> const& obj)
283 -> typename std::reference_wrapper<T>::type const&
284 {
285 return obj.get();
286 }
287 static auto apply(std::reference_wrapper<T>& obj)
288 -> typename std::reference_wrapper<T>::type&
289 {
290 return obj.get();
291 }
292 };
293
294 template <typename F, typename V, typename R, typename... Types>
295 struct dispatcher;
296
297 template <typename F, typename V, typename R, typename T, typename... Types>
298 struct dispatcher<F, V, R, T, Types...>
299 {
300 VARIANT_INLINE static R apply_const(V const& v, F&& f)
301 {
302 if (v.template is<T>())
303 {
304 return f(unwrapper<T>::apply_const(v.template get<T>()));
305 }
306 else
307 {
308 return dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
309 }
310 }
311
312 VARIANT_INLINE static R apply(V& v, F&& f)
313 {
314 if (v.template is<T>())
315 {
316 return f(unwrapper<T>::apply(v.template get<T>()));
317 }
318 else
319 {
320 return dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
321 }
322 }
323 };
324
325 template <typename F, typename V, typename R, typename T>
326 struct dispatcher<F, V, R, T>
327 {
328 VARIANT_INLINE static R apply_const(V const& v, F&& f)
329 {
330 return f(unwrapper<T>::apply_const(v.template get<T>()));
331 }
332
333 VARIANT_INLINE static R apply(V& v, F&& f)
334 {
335 return f(unwrapper<T>::apply(v.template get<T>()));
336 }
337 };
338
339 template <typename F, typename V, typename R, typename T, typename... Types>
340 struct binary_dispatcher_rhs;
341
342 template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
343 struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
344 {
345 VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
346 {
347 if (rhs.template is<T1>()) // call binary functor
348 {
349 return f(unwrapper<T0>::apply_const(lhs.template get<T0>()),
350 unwrapper<T1>::apply_const(rhs.template get<T1>()));
351 }
352 else
353 {
354 return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
355 }
356 }
357
358 VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
359 {
360 if (rhs.template is<T1>()) // call binary functor
361 {
362 return f(unwrapper<T0>::apply(lhs.template get<T0>()),
363 unwrapper<T1>::apply(rhs.template get<T1>()));
364 }
365 else
366 {
367 return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
368 }
369 }
370 };
371
372 template <typename F, typename V, typename R, typename T0, typename T1>
373 struct binary_dispatcher_rhs<F, V, R, T0, T1>
374 {
375 VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
376 {
377 return f(unwrapper<T0>::apply_const(lhs.template get<T0>()),
378 unwrapper<T1>::apply_const(rhs.template get<T1>()));
379 }
380
381 VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
382 {
383 return f(unwrapper<T0>::apply(lhs.template get<T0>()),
384 unwrapper<T1>::apply(rhs.template get<T1>()));
385 }
386 };
387
388 template <typename F, typename V, typename R, typename T, typename... Types>
389 struct binary_dispatcher_lhs;
390
391 template <typename F, typename V, typename R, typename T0, typename T1, typename... Types>
392 struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
393 {
394 VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
395 {
396 if (lhs.template is<T1>()) // call binary functor
397 {
398 return f(unwrapper<T1>::apply_const(lhs.template get<T1>()),
399 unwrapper<T0>::apply_const(rhs.template get<T0>()));
400 }
401 else
402 {
403 return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f));
404 }
405 }
406
407 VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
408 {
409 if (lhs.template is<T1>()) // call binary functor
410 {
411 return f(unwrapper<T1>::apply(lhs.template get<T1>()),
412 unwrapper<T0>::apply(rhs.template get<T0>()));
413 }
414 else
415 {
416 return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
417 }
418 }
419 };
420
421 template <typename F, typename V, typename R, typename T0, typename T1>
422 struct binary_dispatcher_lhs<F, V, R, T0, T1>
423 {
424 VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
425 {
426 return f(unwrapper<T1>::apply_const(lhs.template get<T1>()),
427 unwrapper<T0>::apply_const(rhs.template get<T0>()));
428 }
429
430 VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
431 {
432 return f(unwrapper<T1>::apply(lhs.template get<T1>()),
433 unwrapper<T0>::apply(rhs.template get<T0>()));
434 }
435 };
436
437 template <typename F, typename V, typename R, typename... Types>
438 struct binary_dispatcher;
439
440 template <typename F, typename V, typename R, typename T, typename... Types>
441 struct binary_dispatcher<F, V, R, T, Types...>
442 {
443 VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
444 {
445 if (v0.template is<T>())
446 {
447 if (v1.template is<T>())
448 {
449 return f(unwrapper<T>::apply_const(v0.template get<T>()),
450 unwrapper<T>::apply_const(v1.template get<T>())); // call binary functor
451 }
452 else
453 {
454 return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
455 }
456 }
457 else if (v1.template is<T>())
458 {
459 return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f));
460 }
461 return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
462 }
463
464 VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
465 {
466 if (v0.template is<T>())
467 {
468 if (v1.template is<T>())
469 {
470 return f(unwrapper<T>::apply(v0.template get<T>()),
471 unwrapper<T>::apply(v1.template get<T>())); // call binary functor
472 }
473 else
474 {
475 return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
476 }
477 }
478 else if (v1.template is<T>())
479 {
480 return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
481 }
482 return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
483 }
484 };
485
486 template <typename F, typename V, typename R, typename T>
487 struct binary_dispatcher<F, V, R, T>
488 {
489 VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
490 {
491 return f(unwrapper<T>::apply_const(v0.template get<T>()),
492 unwrapper<T>::apply_const(v1.template get<T>())); // call binary functor
493 }
494
495 VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
496 {
497 return f(unwrapper<T>::apply(v0.template get<T>()),
498 unwrapper<T>::apply(v1.template get<T>())); // call binary functor
499 }
500 };
501
502 // comparator functors
503 struct equal_comp
504 {
505 template <typename T>
506 bool operator()(T const& lhs, T const& rhs) const
507 {
508 return lhs == rhs;
509 }
510 };
511
512 struct less_comp
513 {
514 template <typename T>
515 bool operator()(T const& lhs, T const& rhs) const
516 {
517 return lhs < rhs;
518 }
519 };
520
521 template <typename Variant, typename Comp>
522 class comparer
523 {
524 public:
525 explicit comparer(Variant const& lhs) noexcept
526 : lhs_(lhs) {}
527 comparer& operator=(comparer const&) = delete;
528 // visitor
529 template <typename T>
530 bool operator()(T const& rhs_content) const
531 {
532 T const& lhs_content = lhs_.template get<T>();
533 return Comp()(lhs_content, rhs_content);
534 }
535
536 private:
537 Variant const& lhs_;
538 };
539
540 // True if Predicate matches for all of the types Ts
541 template <template <typename> class Predicate, typename... Ts>
542 struct static_all_of : std::is_same<std::tuple<std::true_type, typename Predicate<Ts>::type...>,
543 std::tuple<typename Predicate<Ts>::type..., std::true_type>>
544 {
545 };
546
547 // True if Predicate matches for none of the types Ts
548 template <template <typename> class Predicate, typename... Ts>
549 struct static_none_of : std::is_same<std::tuple<std::false_type, typename Predicate<Ts>::type...>,
550 std::tuple<typename Predicate<Ts>::type..., std::false_type>>
551 {
552 };
553
554 } // namespace detail
555
556 struct no_init
557 {
558 };
559
560 template <typename... Types>
561 class variant
562 {
563 static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty");
564 static_assert(detail::static_none_of<std::is_reference, Types...>::value, "Variant can not hold reference types. Maybe use std::reference?");
565
566 private:
567 static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
568 static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
569
570 using first_type = typename std::tuple_element<0, std::tuple<Types...>>::type;
571 using data_type = typename std::aligned_storage<data_size, data_align>::type;
572 using helper_type = detail::variant_helper<Types...>;
573
574 std::size_t type_index;
575 data_type data;
576
577 public:
578 VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
579 : type_index(sizeof...(Types)-1)
580 {
581 static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant");
582 new (&data) first_type();
583 }
584
585 VARIANT_INLINE variant(no_init) noexcept
586 : type_index(detail::invalid_value) {}
587
588 // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
589 template <typename T, typename Traits = detail::value_traits<T, Types...>,
590 typename Enable = typename std::enable_if<Traits::is_valid>::type>
591 VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
592 : type_index(Traits::index)
593 {
594 new (&data) typename Traits::target_type(std::forward<T>(val));
595 }
596
597 VARIANT_INLINE variant(variant<Types...> const& old)
598 : type_index(old.type_index)
599 {
600 helper_type::copy(old.type_index, &old.data, &data);
601 }
602
603 VARIANT_INLINE variant(variant<Types...>&& old) noexcept(std::is_nothrow_move_constructible<std::tuple<Types...>>::value)
604 : type_index(old.type_index)
605 {
606 helper_type::move(old.type_index, &old.data, &data);
607 }
608
609 private:
610 VARIANT_INLINE void copy_assign(variant<Types...> const& rhs)
611 {
612 helper_type::destroy(type_index, &data);
613 type_index = detail::invalid_value;
614 helper_type::copy(rhs.type_index, &rhs.data, &data);
615 type_index = rhs.type_index;
616 }
617
618 VARIANT_INLINE void move_assign(variant<Types...>&& rhs)
619 {
620 helper_type::destroy(type_index, &data);
621 type_index = detail::invalid_value;
622 helper_type::move(rhs.type_index, &rhs.data, &data);
623 type_index = rhs.type_index;
624 }
625
626 public:
627 VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
628 {
629 move_assign(std::move(other));
630 return *this;
631 }
632
633 VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
634 {
635 copy_assign(other);
636 return *this;
637 }
638
639 // conversions
640 // move-assign
641 template <typename T>
642 VARIANT_INLINE variant<Types...>& operator=(T&& rhs) noexcept
643 {
644 variant<Types...> temp(std::forward<T>(rhs));
645 move_assign(std::move(temp));
646 return *this;
647 }
648
649 // copy-assign
650 template <typename T>
651 VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
652 {
653 variant<Types...> temp(rhs);
654 copy_assign(temp);
655 return *this;
656 }
657
658 template <typename T>
659 VARIANT_INLINE bool is() const
660 {
661 static_assert(detail::has_type<T, Types...>::value, "invalid type in T in `is<T>()` for this variant");
662 return type_index == detail::direct_type<T, Types...>::index;
663 }
664
665 VARIANT_INLINE bool valid() const
666 {
667 return type_index != detail::invalid_value;
668 }
669
670 template <typename T, typename... Args>
671 VARIANT_INLINE void set(Args&&... args)
672 {
673 helper_type::destroy(type_index, &data);
674 type_index = detail::invalid_value;
675 new (&data) T(std::forward<Args>(args)...);
676 type_index = detail::direct_type<T, Types...>::index;
677 }
678
679 // get<T>()
680 template <typename T, typename std::enable_if<
681 (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
682 VARIANT_INLINE T& get()
683 {
684 if (type_index == detail::direct_type<T, Types...>::index)
685 {
686 return *reinterpret_cast<T*>(&data);
687 }
688 else
689 {
690 throw bad_variant_access("in get<T>()");
691 }
692 }
693
694 template <typename T, typename std::enable_if<
695 (detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
696 VARIANT_INLINE T const& get() const
697 {
698 if (type_index == detail::direct_type<T, Types...>::index)
699 {
700 return *reinterpret_cast<T const*>(&data);
701 }
702 else
703 {
704 throw bad_variant_access("in get<T>()");
705 }
706 }
707
708 // get<T>() - T stored as recursive_wrapper<T>
709 template <typename T, typename std::enable_if<
710 (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
711 VARIANT_INLINE T& get()
712 {
713 if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
714 {
715 return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
716 }
717 else
718 {
719 throw bad_variant_access("in get<T>()");
720 }
721 }
722
723 template <typename T, typename std::enable_if<
724 (detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
725 VARIANT_INLINE T const& get() const
726 {
727 if (type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index)
728 {
729 return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
730 }
731 else
732 {
733 throw bad_variant_access("in get<T>()");
734 }
735 }
736
737 // get<T>() - T stored as std::reference_wrapper<T>
738 template <typename T, typename std::enable_if<
739 (detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
740 VARIANT_INLINE T& get()
741 {
742 if (type_index == detail::direct_type<std::reference_wrapper<T>, Types...>::index)
743 {
744 return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
745 }
746 else
747 {
748 throw bad_variant_access("in get<T>()");
749 }
750 }
751
752 template <typename T, typename std::enable_if<
753 (detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
754 VARIANT_INLINE T const& get() const
755 {
756 if (type_index == detail::direct_type<std::reference_wrapper<T const>, Types...>::index)
757 {
758 return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
759 }
760 else
761 {
762 throw bad_variant_access("in get<T>()");
763 }
764 }
765
766 // This function is deprecated because it returns an internal index field.
767 // Use which() instead.
768 OPENTRACING_VARIANT_DEPRECATED VARIANT_INLINE std::size_t get_type_index() const
769 {
770 return type_index;
771 }
772
773 VARIANT_INLINE int which() const noexcept
774 {
775 return static_cast<int>(sizeof...(Types)-type_index - 1);
776 }
777
778 // visitor
779 // unary
780 template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
781 auto VARIANT_INLINE static visit(V const& v, F&& f)
782 -> decltype(detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)))
783 {
784 return detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f));
785 }
786 // non-const
787 template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
788 auto VARIANT_INLINE static visit(V& v, F&& f)
789 -> decltype(detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f)))
790 {
791 return detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
792 }
793
794 // binary
795 // const
796 template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
797 auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f)
798 -> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)))
799 {
800 return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f));
801 }
802 // non-const
803 template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
804 auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f)
805 -> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f)))
806 {
807 return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
808 }
809
810 ~variant() noexcept // no-throw destructor
811 {
812 helper_type::destroy(type_index, &data);
813 }
814
815 // comparison operators
816 // equality
817 VARIANT_INLINE bool operator==(variant const& rhs) const
818 {
819 assert(valid() && rhs.valid());
820 if (this->which() != rhs.which())
821 {
822 return false;
823 }
824 detail::comparer<variant, detail::equal_comp> visitor(*this);
825 return visit(rhs, visitor);
826 }
827
828 VARIANT_INLINE bool operator!=(variant const& rhs) const
829 {
830 return !(*this == rhs);
831 }
832
833 // less than
834 VARIANT_INLINE bool operator<(variant const& rhs) const
835 {
836 assert(valid() && rhs.valid());
837 if (this->which() != rhs.which())
838 {
839 return this->which() < rhs.which();
840 }
841 detail::comparer<variant, detail::less_comp> visitor(*this);
842 return visit(rhs, visitor);
843 }
844 VARIANT_INLINE bool operator>(variant const& rhs) const
845 {
846 return rhs < *this;
847 }
848 VARIANT_INLINE bool operator<=(variant const& rhs) const
849 {
850 return !(*this > rhs);
851 }
852 VARIANT_INLINE bool operator>=(variant const& rhs) const
853 {
854 return !(*this < rhs);
855 }
856 };
857
858 // unary visitor interface
859 // const
860 template <typename F, typename V>
861 auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward<F>(f)))
862 {
863 return V::visit(v, std::forward<F>(f));
864 }
865
866 // non-const
867 template <typename F, typename V>
868 auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward<F>(f)))
869 {
870 return V::visit(v, std::forward<F>(f));
871 }
872
873 // binary visitor interface
874 // const
875 template <typename F, typename V>
876 auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
877 {
878 return V::binary_visit(v0, v1, std::forward<F>(f));
879 }
880
881 // non-const
882 template <typename F, typename V>
883 auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
884 {
885 return V::binary_visit(v0, v1, std::forward<F>(f));
886 }
887
888 // getter interface
889 template <typename ResultType, typename T>
890 ResultType& get(T& var)
891 {
892 return var.template get<ResultType>();
893 }
894
895 template <typename ResultType, typename T>
896 ResultType const& get(T const& var)
897 {
898 return var.template get<ResultType>();
899 }
900 } // namespace util
901 END_OPENTRACING_ABI_NAMESPACE
902 } // namespace opentracing
903
904 #endif // OPENTRACING_UTIL_VARIANT_HPP