123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2017 Realm Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- ////////////////////////////////////////////////////////////////////////////
- #ifndef REALM_UTIL_ANY_HPP
- #define REALM_UTIL_ANY_HPP
- #include <memory>
- #include <stdexcept>
- #include <type_traits>
- #include <typeinfo>
- #include <realm/util/backtrace.hpp>
- namespace realm {
- namespace util {
- using bad_cast = std::bad_cast;
- // A naive implementation of C++17's std::any
- // This does not perform the small-object optimization or make any particular
- // attempt at being performant
- class Any final {
- public:
- // Constructors
- Any() = default;
- Any(Any&&) noexcept = default;
- ~Any() = default;
- Any& operator=(Any&&) noexcept = default;
- Any(Any const& rhs)
- : m_value(rhs.m_value ? rhs.m_value->copy() : nullptr)
- {
- }
- template<typename T, typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, Any>::value>::type>
- Any(T&& value)
- : m_value(std::make_unique<Value<typename std::decay<T>::type>>(std::forward<T>(value)))
- {
- }
- Any& operator=(Any const& rhs)
- {
- m_value = rhs.m_value ? rhs.m_value->copy() : nullptr;
- return *this;
- }
- template<typename T, typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, Any>::value>::type>
- Any& operator=(T&& value)
- {
- m_value = std::make_unique<Value<typename std::decay<T>::type>>(std::forward<T>(value));
- return *this;
- }
- // Modifiers
- void reset() noexcept { m_value.reset(); }
- void swap(Any& rhs) noexcept { std::swap(m_value, rhs.m_value); }
- // Observers
- bool has_value() const noexcept { return m_value != nullptr; }
- std::type_info const& type() const noexcept { return m_value ? m_value->type() : typeid(void); }
- private:
- struct ValueBase {
- virtual ~ValueBase() noexcept { }
- virtual std::type_info const& type() const noexcept = 0;
- virtual std::unique_ptr<ValueBase> copy() const = 0;
- };
- template<typename T>
- struct Value : ValueBase {
- T value;
- template<typename U> Value(U&& v) : value(std::forward<U>(v)) { }
- std::type_info const& type() const noexcept override { return typeid(T); }
- std::unique_ptr<ValueBase> copy() const override
- {
- return std::make_unique<Value<T>>(value);
- }
- };
- std::unique_ptr<ValueBase> m_value;
- template<typename T>
- friend const T* any_cast(const Any* operand) noexcept;
- template<typename T>
- friend T* any_cast(Any* operand) noexcept;
- template<typename T>
- const T* cast() const noexcept
- {
- return &static_cast<Value<T>*>(m_value.get())->value;
- }
- template<typename T>
- T* cast() noexcept
- {
- return &static_cast<Value<T>*>(m_value.get())->value;
- }
- };
- template<typename T>
- T any_cast(Any const& value)
- {
- auto ptr = any_cast<typename std::add_const<typename std::remove_reference<T>::type>::type>(&value);
- if (!ptr)
- throw bad_cast();
- return *ptr;
- }
- template<typename T>
- T any_cast(Any& value)
- {
- auto ptr = any_cast<typename std::remove_reference<T>::type>(&value);
- if (!ptr)
- throw bad_cast();
- return *ptr;
- }
- template<typename T>
- T any_cast(Any&& value)
- {
- auto ptr = any_cast<typename std::remove_reference<T>::type>(&value);
- if (!ptr)
- throw bad_cast();
- return std::move(*ptr);
- }
- template<typename T>
- T* any_cast(Any* value) noexcept
- {
- return value && value->type() == typeid(T) ? value->cast<T>() : nullptr;
- }
- template<typename T>
- const T* any_cast(const Any* value) noexcept
- {
- return value && value->type() == typeid(T) ? value->cast<T>() : nullptr;
- }
- } // namespace util
- } // namespace realm
- namespace std {
- inline void swap(realm::util::Any& lhs, realm::util::Any& rhs) noexcept
- {
- lhs.swap(rhs);
- }
- } // namespace std
- #endif // REALM_UTIL_ANY_HPP
|