any.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // This file is distributed under the BSD License.
  2. // See "license.txt" for details.
  3. // Copyright 2009-2012, Jonathan Turner ([email protected])
  4. // and Jason Turner ([email protected])
  5. // http://www.chaiscript.com
  6. #ifndef CHAISCRIPT_ANY_HPP_
  7. #define CHAISCRIPT_ANY_HPP_
  8. #include <utility>
  9. namespace chaiscript {
  10. namespace detail {
  11. namespace exception
  12. {
  13. /// \brief Thrown in the event that an Any cannot be cast to the desired type
  14. ///
  15. /// It is used internally during function dispatch.
  16. ///
  17. /// \sa chaiscript::detail::Any
  18. class bad_any_cast : public std::bad_cast
  19. {
  20. public:
  21. bad_any_cast() = default;
  22. bad_any_cast(const bad_any_cast &) = default;
  23. ~bad_any_cast() noexcept override = default;
  24. /// \brief Description of what error occurred
  25. const char * what() const noexcept override
  26. {
  27. return m_what.c_str();
  28. }
  29. private:
  30. std::string m_what = "bad any cast";
  31. };
  32. }
  33. class Any {
  34. private:
  35. struct Data
  36. {
  37. explicit Data(const std::type_info &t_type)
  38. : m_type(t_type)
  39. {
  40. }
  41. Data &operator=(const Data &) = delete;
  42. virtual ~Data() = default;
  43. virtual void *data() = 0;
  44. const std::type_info &type() const
  45. {
  46. return m_type;
  47. }
  48. virtual std::unique_ptr<Data> clone() const = 0;
  49. const std::type_info &m_type;
  50. };
  51. template<typename T>
  52. struct Data_Impl : Data
  53. {
  54. explicit Data_Impl(T t_type)
  55. : Data(typeid(T)),
  56. m_data(std::move(t_type))
  57. {
  58. }
  59. void *data() override
  60. {
  61. return &m_data;
  62. }
  63. std::unique_ptr<Data> clone() const override
  64. {
  65. return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
  66. }
  67. Data_Impl &operator=(const Data_Impl&) = delete;
  68. T m_data;
  69. };
  70. std::unique_ptr<Data> m_data;
  71. public:
  72. // construct/copy/destruct
  73. Any() = default;
  74. Any(Any &&) = default;
  75. Any &operator=(Any &&t_any) = default;
  76. Any(const Any &t_any)
  77. {
  78. if (!t_any.empty())
  79. {
  80. m_data = t_any.m_data->clone();
  81. } else {
  82. m_data.reset();
  83. }
  84. }
  85. template<typename ValueType,
  86. typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
  87. explicit Any(ValueType &&t_value)
  88. : m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value))))
  89. {
  90. }
  91. Any & operator=(const Any &t_any)
  92. {
  93. Any copy(t_any);
  94. swap(copy);
  95. return *this;
  96. }
  97. template<typename ToType>
  98. ToType &cast() const
  99. {
  100. if (m_data && typeid(ToType) == m_data->type())
  101. {
  102. return *static_cast<ToType *>(m_data->data());
  103. } else {
  104. throw chaiscript::detail::exception::bad_any_cast();
  105. }
  106. }
  107. // modifiers
  108. Any & swap(Any &t_other)
  109. {
  110. std::swap(t_other.m_data, m_data);
  111. return *this;
  112. }
  113. // queries
  114. bool empty() const
  115. {
  116. return !bool(m_data);
  117. }
  118. const std::type_info & type() const
  119. {
  120. if (m_data) {
  121. return m_data->type();
  122. } else {
  123. return typeid(void);
  124. }
  125. }
  126. };
  127. }
  128. }
  129. #endif