blob: fe1ab3543248503de2de47f1e135775a55a63443 [file] [log] [blame]
James Ward22a4e152020-09-25 11:43:21 +01001#ifndef VARIANT_CAST_HPP
2#define VARIANT_CAST_HPP
3
4#include <type_traits>
5
6namespace mapbox {
7namespace util {
8
9namespace detail {
10
11template <class T>
12class static_caster
13{
14public:
15 template <class V>
16 T& operator()(V& v) const
17 {
18 return static_cast<T&>(v);
19 }
20};
21
22template <class T>
23class dynamic_caster
24{
25public:
26 using result_type = T&;
27 template <class V>
28 T& operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
29 {
30 throw std::bad_cast();
31 }
32 template <class V>
33 T& operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
34 {
35 return dynamic_cast<T&>(v);
36 }
37};
38
39template <class T>
40class dynamic_caster<T*>
41{
42public:
43 using result_type = T*;
44 template <class V>
45 T* operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
46 {
47 return nullptr;
48 }
49 template <class V>
50 T* operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
51 {
52 return dynamic_cast<T*>(&v);
53 }
54};
55}
56
57template <class T, class V>
58typename detail::dynamic_caster<T>::result_type
59dynamic_variant_cast(V& v)
60{
61 return mapbox::util::apply_visitor(detail::dynamic_caster<T>(), v);
62}
63
64template <class T, class V>
65typename detail::dynamic_caster<const T>::result_type
66dynamic_variant_cast(const V& v)
67{
68 return mapbox::util::apply_visitor(detail::dynamic_caster<const T>(), v);
69}
70
71template <class T, class V>
72T& static_variant_cast(V& v)
73{
74 return mapbox::util::apply_visitor(detail::static_caster<T>(), v);
75}
76
77template <class T, class V>
78const T& static_variant_cast(const V& v)
79{
80 return mapbox::util::apply_visitor(detail::static_caster<const T>(), v);
81}
82}
83}
84
85#endif // VARIANT_CAST_HPP