blob: 0795bcf40ec06ab1c2cdbbf8b3dcc3e7edc6cb11 [file] [log] [blame]
Jim Flynn6217c3d2022-06-14 10:58:23 +01001//
2// Copyright (c) MapBox All rights reserved.
3// SPDX-License-Identifier: BSD-3-Clause
4//
5
James Ward22a4e152020-09-25 11:43:21 +01006#ifndef VARIANT_CAST_HPP
7#define VARIANT_CAST_HPP
8
9#include <type_traits>
10
11namespace mapbox {
12namespace util {
13
14namespace detail {
15
16template <class T>
17class static_caster
18{
19public:
20 template <class V>
21 T& operator()(V& v) const
22 {
23 return static_cast<T&>(v);
24 }
25};
26
27template <class T>
28class dynamic_caster
29{
30public:
31 using result_type = T&;
32 template <class V>
33 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>
38 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
44template <class T>
45class dynamic_caster<T*>
46{
47public:
48 using result_type = T*;
49 template <class V>
50 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>
55 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
62template <class T, class V>
63typename detail::dynamic_caster<T>::result_type
64dynamic_variant_cast(V& v)
65{
66 return mapbox::util::apply_visitor(detail::dynamic_caster<T>(), v);
67}
68
69template <class T, class V>
70typename detail::dynamic_caster<const T>::result_type
71dynamic_variant_cast(const V& v)
72{
73 return mapbox::util::apply_visitor(detail::dynamic_caster<const T>(), v);
74}
75
76template <class T, class V>
77T& static_variant_cast(V& v)
78{
79 return mapbox::util::apply_visitor(detail::static_caster<T>(), v);
80}
81
82template <class T, class V>
83const 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