1 ////////////////////////////////////////////////////////////////////////////
3 // Copyright 2017 Realm Inc.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 ////////////////////////////////////////////////////////////////////////////
19 #ifndef REALM_UTIL_ANY_HPP
20 #define REALM_UTIL_ANY_HPP
24 #include <type_traits>
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
38 Any(Any&&) noexcept = default;
40 Any& operator=(Any&&) noexcept = default;
43 : m_value(rhs.m_value ? rhs.m_value->copy() : nullptr)
47 template<typename T, typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, Any>::value>::type>
49 : m_value(std::make_unique<Value<typename std::decay<T>::type>>(std::forward<T>(value)))
53 Any& operator=(Any const& rhs)
55 m_value = rhs.m_value ? rhs.m_value->copy() : nullptr;
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)
62 m_value = std::make_unique<Value<typename std::decay<T>::type>>(std::forward<T>(value));
68 void reset() noexcept { m_value.reset(); }
69 void swap(Any& rhs) noexcept { std::swap(m_value, rhs.m_value); }
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); }
78 virtual ~ValueBase() noexcept { }
79 virtual std::type_info const& type() const noexcept = 0;
80 virtual std::unique_ptr<ValueBase> copy() const = 0;
83 struct Value : ValueBase {
85 template<typename U> Value(U&& v) : value(std::forward<U>(v)) { }
87 std::type_info const& type() const noexcept override { return typeid(T); }
88 std::unique_ptr<ValueBase> copy() const override
90 return std::make_unique<Value<T>>(value);
93 std::unique_ptr<ValueBase> m_value;
96 friend const T* any_cast(const Any* operand) noexcept;
98 friend T* any_cast(Any* operand) noexcept;
101 const T* cast() const noexcept
103 return &static_cast<Value<T>*>(m_value.get())->value;
109 return &static_cast<Value<T>*>(m_value.get())->value;
114 T any_cast(Any const& value)
116 auto ptr = any_cast<typename std::add_const<typename std::remove_reference<T>::type>::type>(&value);
118 throw std::bad_cast();
123 T any_cast(Any& value)
125 auto ptr = any_cast<typename std::remove_reference<T>::type>(&value);
127 throw std::bad_cast();
132 T any_cast(Any&& value)
134 auto ptr = any_cast<typename std::remove_reference<T>::type>(&value);
136 throw std::bad_cast();
137 return std::move(*ptr);
141 T* any_cast(Any* value) noexcept
143 return value && value->type() == typeid(T) ? value->cast<T>() : nullptr;
147 const T* any_cast(const Any* value) noexcept
149 return value && value->type() == typeid(T) ? value->cast<T>() : nullptr;
155 inline void swap(realm::util::Any& lhs, realm::util::Any& rhs) noexcept
161 #endif // REALM_UTIL_ANY_HPP