1 //
2 // Copyright (c) MapBox All rights reserved.
3 // SPDX-License-Identifier: BSD-3-Clause
4 //
5
6 #ifndef VARIANT_CAST_HPP
7 #define VARIANT_CAST_HPP
8
9 #include <type_traits>
10
11 namespace mapbox {
12 namespace util {
13
14 namespace detail {
15
16 template <class T>
17 class static_caster
18 {
19 public:
20 template <class V>
operator ()(V & v) const21 T& operator()(V& v) const
22 {
23 return static_cast<T&>(v);
24 }
25 };
26
27 template <class T>
28 class dynamic_caster
29 {
30 public:
31 using result_type = T&;
32 template <class V>
operator ()(V & v,typename std::enable_if<!std::is_polymorphic<V>::value>::type * =nullptr) const33 T& operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
34 {
35 throw std::bad_cast();
36 }
37 template <class V>
operator ()(V & v,typename std::enable_if<std::is_polymorphic<V>::value>::type * =nullptr) const38 T& operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
39 {
40 return dynamic_cast<T&>(v);
41 }
42 };
43
44 template <class T>
45 class dynamic_caster<T*>
46 {
47 public:
48 using result_type = T*;
49 template <class V>
operator ()(V & v,typename std::enable_if<!std::is_polymorphic<V>::value>::type * =nullptr) const50 T* operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
51 {
52 return nullptr;
53 }
54 template <class V>
operator ()(V & v,typename std::enable_if<std::is_polymorphic<V>::value>::type * =nullptr) const55 T* operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
56 {
57 return dynamic_cast<T*>(&v);
58 }
59 };
60 }
61
62 template <class T, class V>
63 typename detail::dynamic_caster<T>::result_type
dynamic_variant_cast(V & v)64 dynamic_variant_cast(V& v)
65 {
66 return mapbox::util::apply_visitor(detail::dynamic_caster<T>(), v);
67 }
68
69 template <class T, class V>
70 typename detail::dynamic_caster<const T>::result_type
dynamic_variant_cast(const V & v)71 dynamic_variant_cast(const V& v)
72 {
73 return mapbox::util::apply_visitor(detail::dynamic_caster<const T>(), v);
74 }
75
76 template <class T, class V>
static_variant_cast(V & v)77 T& static_variant_cast(V& v)
78 {
79 return mapbox::util::apply_visitor(detail::static_caster<T>(), v);
80 }
81
82 template <class T, class V>
static_variant_cast(const V & v)83 const T& static_variant_cast(const V& v)
84 {
85 return mapbox::util::apply_visitor(detail::static_caster<const T>(), v);
86 }
87 }
88 }
89
90 #endif // VARIANT_CAST_HPP
91