#pragma once #include "BsPrerequisitesUtil.h" #include "BsDebug.h" #include #include namespace BansheeEngine { /** @addtogroup General * @{ */ /** Class capable of storing any general type, and safely extracting the proper type from the internal data. */ class Any { private: class DataBase { public: virtual ~DataBase() { } virtual DataBase* clone() const = 0; }; template class Data : public DataBase { public: Data(const ValueType& value) :value(value) { } virtual DataBase* clone() const override { return new Data(value); } ValueType value; }; public: Any() :mData(nullptr) { } template Any(const ValueType& value) :mData(bs_new>(value)) { } Any(const Any& other) :mData(other.mData != nullptr ? other.mData->clone() : nullptr) { } ~Any() { if (mData != nullptr) bs_delete(mData); } /** Swaps the contents of this object with another. */ Any& swap(Any& rhs) { std::swap(mData, rhs.mData); return *this; } template Any& operator= (const ValueType& rhs) { Any(rhs).swap(*this); return *this; } Any& operator= (const Any& rhs) { Any(rhs).swap(*this); return *this; } /** Returns true if no type is set. */ bool empty() const { return mData == nullptr; } private: template friend ValueType* any_cast(Any*); template friend ValueType* any_cast_unsafe(Any*); DataBase* mData; }; /** * Returns a pointer to the internal data of the specified type. * * @note Will return null if cast fails. */ template ValueType* any_cast(Any* operand) { if (operand != nullptr) return &static_cast*>(operand->mData)->value; else return nullptr; } /** * Returns a const pointer to the internal data of the specified type. * * @note Will return null if cast fails. */ template const ValueType* any_cast(const Any* operand) { return any_cast(const_cast(operand)); } /** * Returns a copy of the internal data of the specified type. * * @note Throws an exception if cast fails. */ template ValueType any_cast(const Any& operand) { return *any_cast(const_cast(&operand)); } /** * Returns a copy of the internal data of the specified type. * * @note Throws an exception if cast fails. */ template ValueType any_cast(Any& operand) { return *any_cast(&operand); } /** * Returns a reference to the internal data of the specified type. * * @note Throws an exception if cast fails. */ template const ValueType& any_cast_ref(const Any & operand) { return *any_cast(const_cast(&operand)); } /** * Returns a reference to the internal data of the specified type. * * @note Throws an exception if cast fails. */ template ValueType& any_cast_ref(Any& operand) { return *any_cast(&operand); } /** Casts a type without performing any kind of checks. */ template ValueType* any_cast_unsafe(Any* operand) { return &static_cast*>(operand->mData)->value; } /** Casts a type without performing any kind of checks. */ template const ValueType* any_cast_unsafe(const Any* operand) { return any_cast_unsafe(const_cast(operand)); } /** @} */ }