added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / util / any.hpp
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2017 Realm Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #ifndef REALM_UTIL_ANY_HPP
20 #define REALM_UTIL_ANY_HPP
21
22 #include <memory>
23 #include <stdexcept>
24 #include <type_traits>
25 #include <typeinfo>
26
27 namespace realm {
28 namespace util {
29
30 // A naive implementation of C++17's std::any
31 // This does not perform the small-object optimization or make any particular
32 // attempt at being performant
33 class Any final {
34 public:
35     // Constructors
36
37     Any() = default;
38     Any(Any&&) noexcept = default;
39     ~Any() = default;
40     Any& operator=(Any&&) noexcept = default;
41
42     Any(Any const& rhs)
43     : m_value(rhs.m_value ? rhs.m_value->copy() : nullptr)
44     {
45     }
46
47     template<typename T, typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, Any>::value>::type>
48     Any(T&& value)
49     : m_value(std::make_unique<Value<typename std::decay<T>::type>>(std::forward<T>(value)))
50     {
51     }
52
53     Any& operator=(Any const& rhs)
54     {
55         m_value = rhs.m_value ? rhs.m_value->copy() : nullptr;
56         return *this;
57     }
58
59     template<typename T, typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, Any>::value>::type>
60     Any& operator=(T&& value)
61     {
62         m_value = std::make_unique<Value<typename std::decay<T>::type>>(std::forward<T>(value));
63         return *this;
64     }
65
66     // Modifiers
67
68     void reset() noexcept { m_value.reset(); }
69     void swap(Any& rhs) noexcept { std::swap(m_value, rhs.m_value); }
70
71     // Observers
72
73     bool has_value() const noexcept { return m_value != nullptr; }
74     std::type_info const& type() const noexcept { return m_value ? m_value->type() : typeid(void); }
75
76 private:
77     struct ValueBase {
78         virtual ~ValueBase() noexcept { }
79         virtual std::type_info const& type() const noexcept = 0;
80         virtual std::unique_ptr<ValueBase> copy() const = 0;
81     };
82     template<typename T>
83     struct Value : ValueBase {
84         T value;
85         template<typename U> Value(U&& v) : value(std::forward<U>(v)) { }
86
87         std::type_info const& type() const noexcept override { return typeid(T); }
88         std::unique_ptr<ValueBase> copy() const override
89         {
90             return std::make_unique<Value<T>>(value);
91         }
92     };
93     std::unique_ptr<ValueBase> m_value;
94
95     template<typename T>
96     friend const T* any_cast(const Any* operand) noexcept;
97     template<typename T>
98     friend T* any_cast(Any* operand) noexcept;
99
100     template<typename T>
101     const T* cast() const noexcept
102     {
103         return &static_cast<Value<T>*>(m_value.get())->value;
104     }
105
106     template<typename T>
107     T* cast() noexcept
108     {
109         return &static_cast<Value<T>*>(m_value.get())->value;
110     }
111 };
112
113 template<typename T>
114 T any_cast(Any const& value)
115 {
116     auto ptr = any_cast<typename std::add_const<typename std::remove_reference<T>::type>::type>(&value);
117     if (!ptr)
118         throw std::bad_cast();
119     return *ptr;
120 }
121
122 template<typename T>
123 T any_cast(Any& value)
124 {
125     auto ptr = any_cast<typename std::remove_reference<T>::type>(&value);
126     if (!ptr)
127         throw std::bad_cast();
128     return *ptr;
129 }
130
131 template<typename T>
132 T any_cast(Any&& value)
133 {
134     auto ptr = any_cast<typename std::remove_reference<T>::type>(&value);
135     if (!ptr)
136         throw std::bad_cast();
137     return std::move(*ptr);
138 }
139
140 template<typename T>
141 T* any_cast(Any* value) noexcept
142 {
143     return value && value->type() == typeid(T) ? value->cast<T>() : nullptr;
144 }
145
146 template<typename T>
147 const T* any_cast(const Any* value) noexcept
148 {
149     return value && value->type() == typeid(T) ? value->cast<T>() : nullptr;
150 }
151 } // namespace util
152 } // namespace realm
153
154 namespace std {
155 inline void swap(realm::util::Any& lhs, realm::util::Any& rhs) noexcept
156 {
157     lhs.swap(rhs);
158 }
159 } // namespace std
160
161 #endif // REALM_UTIL_ANY_HPP