BsAny.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsPrerequisitesUtil.h"
  5. #include "BsDebug.h"
  6. #include <algorithm>
  7. #include <typeinfo>
  8. namespace BansheeEngine
  9. {
  10. /** @addtogroup General
  11. * @{
  12. */
  13. /** Class capable of storing any general type, and safely extracting the proper type from the internal data. */
  14. class Any
  15. {
  16. private:
  17. class DataBase
  18. {
  19. public:
  20. virtual ~DataBase()
  21. { }
  22. virtual DataBase* clone() const = 0;
  23. };
  24. template <typename ValueType>
  25. class Data : public DataBase
  26. {
  27. public:
  28. Data(const ValueType& value)
  29. :value(value)
  30. { }
  31. virtual DataBase* clone() const override
  32. {
  33. return new Data(value);
  34. }
  35. ValueType value;
  36. };
  37. public:
  38. Any()
  39. :mData(nullptr)
  40. { }
  41. template <typename ValueType>
  42. Any(const ValueType& value)
  43. :mData(bs_new<Data<ValueType>>(value))
  44. { }
  45. Any(std::nullptr_t)
  46. :mData(nullptr)
  47. { }
  48. Any(const Any& other)
  49. :mData(other.mData != nullptr ? other.mData->clone() : nullptr)
  50. { }
  51. ~Any()
  52. {
  53. if (mData != nullptr)
  54. bs_delete(mData);
  55. }
  56. /** Swaps the contents of this object with another. */
  57. Any& swap(Any& rhs)
  58. {
  59. std::swap(mData, rhs.mData);
  60. return *this;
  61. }
  62. template <typename ValueType>
  63. Any& operator= (const ValueType& rhs)
  64. {
  65. Any(rhs).swap(*this);
  66. return *this;
  67. }
  68. Any& operator= (const Any& rhs)
  69. {
  70. Any(rhs).swap(*this);
  71. return *this;
  72. }
  73. /** Returns true if no type is set. */
  74. bool empty() const
  75. {
  76. return mData == nullptr;
  77. }
  78. private:
  79. template <typename ValueType>
  80. friend ValueType* any_cast(Any*);
  81. template <typename ValueType>
  82. friend ValueType* any_cast_unsafe(Any*);
  83. DataBase* mData;
  84. };
  85. /**
  86. * Returns a pointer to the internal data of the specified type.
  87. *
  88. * @note Will return null if cast fails.
  89. */
  90. template <typename ValueType>
  91. ValueType* any_cast(Any* operand)
  92. {
  93. if (operand != nullptr)
  94. return &static_cast<Any::Data<ValueType>*>(operand->mData)->value;
  95. else
  96. return nullptr;
  97. }
  98. /**
  99. * Returns a const pointer to the internal data of the specified type.
  100. *
  101. * @note Will return null if cast fails.
  102. */
  103. template <typename ValueType>
  104. const ValueType* any_cast(const Any* operand)
  105. {
  106. return any_cast<ValueType>(const_cast<Any*>(operand));
  107. }
  108. /**
  109. * Returns a copy of the internal data of the specified type.
  110. *
  111. * @note Throws an exception if cast fails.
  112. */
  113. template <typename ValueType>
  114. ValueType any_cast(const Any& operand)
  115. {
  116. return *any_cast<ValueType>(const_cast<Any*>(&operand));
  117. }
  118. /**
  119. * Returns a copy of the internal data of the specified type.
  120. *
  121. * @note Throws an exception if cast fails.
  122. */
  123. template <typename ValueType>
  124. ValueType any_cast(Any& operand)
  125. {
  126. return *any_cast<ValueType>(&operand);
  127. }
  128. /**
  129. * Returns a reference to the internal data of the specified type.
  130. *
  131. * @note Throws an exception if cast fails.
  132. */
  133. template <typename ValueType>
  134. const ValueType& any_cast_ref(const Any & operand)
  135. {
  136. return *any_cast<ValueType>(const_cast<Any*>(&operand));
  137. }
  138. /**
  139. * Returns a reference to the internal data of the specified type.
  140. *
  141. * @note Throws an exception if cast fails.
  142. */
  143. template <typename ValueType>
  144. ValueType& any_cast_ref(Any& operand)
  145. {
  146. return *any_cast<ValueType>(&operand);
  147. }
  148. /** Casts a type without performing any kind of checks. */
  149. template <typename ValueType>
  150. ValueType* any_cast_unsafe(Any* operand)
  151. {
  152. return &static_cast<Any::Data<ValueType>*>(operand->mData)->value;
  153. }
  154. /** Casts a type without performing any kind of checks. */
  155. template <typename ValueType>
  156. const ValueType* any_cast_unsafe(const Any* operand)
  157. {
  158. return any_cast_unsafe<ValueType>(const_cast<Any*>(operand));
  159. }
  160. /** @} */
  161. }