/** * Any * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * @file nana/any.hpp * * @brief An implementation of experimental library any of C++ standard(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#any) */ #ifndef NANA_ANY_HPP #define NANA_ANY_HPP #include #include #include "c++defines.hpp" namespace nana { class bad_any_cast : public std::bad_cast { }; class any { class content_interface { public: virtual ~content_interface() = default; virtual const std::type_info& type() const noexcept = 0; virtual content_interface* clone() const = 0; }; template class holder : public content_interface { holder& operator=(const holder&) = delete; public: holder(const Value& other) : value(other) {} holder(Value&& other) : value(static_cast(other)) {} public: const std::type_info& type() const noexcept override { return typeid(Value); } content_interface* clone() const override { return new holder(value); } public: Value value; //representation accessable for friend of any }; public: //constructors and destructor any() noexcept; any(const any& other); any(any&& other) noexcept; template any(Value && value, typename std::enable_if::value>::type * = nullptr, typename std::enable_if::value>::type* = nullptr) : content_(new holder::type>(static_cast(value))) { } ~any(); //assignments any& operator=(const any& other); any& operator=(any&& other) noexcept; template any& operator=(Value&& other) { any(other).swap(*this); return *this; } //modifiers void clear() noexcept; void swap(any& other) noexcept; //observers bool empty() const noexcept; const std::type_info& type() const noexcept; private: template friend Value* any_cast(any*) noexcept; private: content_interface * content_; }; // Non-member functions inline void swap(any& x, any& y) noexcept { x.swap(y); } template Value any_cast(const any& operand) { using value_type = typename std::remove_reference::type; return any_cast(const_cast(operand)); } template Value any_cast(any& operand) { using value_type = typename std::remove_reference::type; auto value_ptr = any_cast(&operand); if (!value_ptr) throw bad_any_cast(); using ref_type = typename std::conditional::value, Value, typename std::add_lvalue_reference::type>::type; return static_cast(*value_ptr); } template Value any_cast(any && operand) { static_assert(std::is_rvalue_reference::value || std::is_const::type>::value, "nana::any_cast shall not be used for getting non-const reference to temporary objects"); return any_cast(operand); } template const Value* any_cast(const any* operand) noexcept { return any_cast(const_cast(operand)); } template Value* any_cast(any* operand) noexcept { if (!operand) return nullptr; auto holder = dynamic_cast::type>*>(operand->content_); return (holder ? &holder->value : nullptr); } }//end namespace nana #endif