type_info.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // This file is distributed under the BSD License.
  2. // See "license.txt" for details.
  3. // Copyright 2009-2012, Jonathan Turner ([email protected])
  4. // Copyright 2009-2017, Jason Turner ([email protected])
  5. // http://www.chaiscript.com
  6. // This is an open source non-commercial project. Dear PVS-Studio, please check it.
  7. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
  8. #ifndef CHAISCRIPT_TYPE_INFO_HPP_
  9. #define CHAISCRIPT_TYPE_INFO_HPP_
  10. #include <memory>
  11. #include <type_traits>
  12. #include <typeinfo>
  13. #include <string>
  14. namespace chaiscript
  15. {
  16. namespace detail
  17. {
  18. template<typename T>
  19. struct Bare_Type
  20. {
  21. typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
  22. };
  23. }
  24. /// \brief Compile time deduced information about a type
  25. class Type_Info
  26. {
  27. public:
  28. constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
  29. const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
  30. : m_type_info(t_ti), m_bare_type_info(t_bare_ti),
  31. m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
  32. + (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
  33. + (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
  34. + (static_cast<unsigned int>(t_is_void) << is_void_flag)
  35. + (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
  36. {
  37. }
  38. constexpr Type_Info() = default;
  39. constexpr bool operator<(const Type_Info &ti) const noexcept
  40. {
  41. return m_type_info < ti.m_type_info;
  42. }
  43. constexpr bool operator!=(const Type_Info &ti) const noexcept
  44. {
  45. return !(operator==(ti));
  46. }
  47. constexpr bool operator!=(const std::type_info &ti) const noexcept
  48. {
  49. return !(operator==(ti));
  50. }
  51. constexpr bool operator==(const Type_Info &ti) const noexcept
  52. {
  53. return ti.m_type_info == m_type_info
  54. || *ti.m_type_info == *m_type_info;
  55. }
  56. constexpr bool operator==(const std::type_info &ti) const noexcept
  57. {
  58. return !is_undef() && (*m_type_info) == ti;
  59. }
  60. constexpr bool bare_equal(const Type_Info &ti) const noexcept
  61. {
  62. return ti.m_bare_type_info == m_bare_type_info
  63. || *ti.m_bare_type_info == *m_bare_type_info;
  64. }
  65. constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
  66. {
  67. return !is_undef() && (*m_bare_type_info) == ti;
  68. }
  69. constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
  70. constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
  71. constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
  72. constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
  73. constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
  74. constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
  75. std::string name() const
  76. {
  77. if (!is_undef())
  78. {
  79. return m_type_info->name();
  80. } else {
  81. return "";
  82. }
  83. }
  84. std::string bare_name() const
  85. {
  86. if (!is_undef())
  87. {
  88. return m_bare_type_info->name();
  89. } else {
  90. return "";
  91. }
  92. }
  93. constexpr const std::type_info *bare_type_info() const
  94. {
  95. return m_bare_type_info;
  96. }
  97. private:
  98. struct Unknown_Type {};
  99. const std::type_info *m_type_info = &typeid(Unknown_Type);
  100. const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
  101. static const int is_const_flag = 0;
  102. static const int is_reference_flag = 1;
  103. static const int is_pointer_flag = 2;
  104. static const int is_void_flag = 3;
  105. static const int is_arithmetic_flag = 4;
  106. static const int is_undef_flag = 5;
  107. unsigned int m_flags = (1 << is_undef_flag);
  108. };
  109. namespace detail
  110. {
  111. /// Helper used to create a Type_Info object
  112. template<typename T>
  113. struct Get_Type_Info
  114. {
  115. static constexpr Type_Info get()
  116. {
  117. return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
  118. std::is_reference<T>::value, std::is_pointer<T>::value,
  119. std::is_void<T>::value,
  120. (std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
  121. && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
  122. &typeid(T),
  123. &typeid(typename Bare_Type<T>::type));
  124. }
  125. };
  126. template<typename T>
  127. struct Get_Type_Info<std::shared_ptr<T> >
  128. {
  129. // typedef T type;
  130. static constexpr Type_Info get()
  131. {
  132. return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
  133. std::is_void<T>::value,
  134. std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
  135. &typeid(std::shared_ptr<T> ),
  136. &typeid(typename Bare_Type<T>::type));
  137. }
  138. };
  139. template<typename T>
  140. struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
  141. {
  142. };
  143. template<typename T>
  144. struct Get_Type_Info<const std::shared_ptr<T> &>
  145. {
  146. static constexpr Type_Info get()
  147. {
  148. return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
  149. std::is_void<T>::value,
  150. std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
  151. &typeid(const std::shared_ptr<T> &),
  152. &typeid(typename Bare_Type<T>::type));
  153. }
  154. };
  155. template<typename T>
  156. struct Get_Type_Info<std::reference_wrapper<T> >
  157. {
  158. static constexpr Type_Info get()
  159. {
  160. return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
  161. std::is_void<T>::value,
  162. std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
  163. &typeid(std::reference_wrapper<T> ),
  164. &typeid(typename Bare_Type<T>::type));
  165. }
  166. };
  167. template<typename T>
  168. struct Get_Type_Info<const std::reference_wrapper<T> &>
  169. {
  170. static constexpr Type_Info get()
  171. {
  172. return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
  173. std::is_void<T>::value,
  174. std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
  175. &typeid(const std::reference_wrapper<T> &),
  176. &typeid(typename Bare_Type<T>::type));
  177. }
  178. };
  179. }
  180. /// \brief Creates a Type_Info object representing the type passed in
  181. /// \tparam T Type of object to get a Type_Info for, derived from the passed in parameter
  182. /// \return Type_Info for T
  183. ///
  184. /// \b Example:
  185. /// \code
  186. /// int i;
  187. /// chaiscript::Type_Info ti = chaiscript::user_type(i);
  188. /// \endcode
  189. template<typename T>
  190. constexpr Type_Info user_type(const T &/*t*/)
  191. {
  192. return detail::Get_Type_Info<T>::get();
  193. }
  194. /// \brief Creates a Type_Info object representing the templated type
  195. /// \tparam T Type of object to get a Type_Info for
  196. /// \return Type_Info for T
  197. ///
  198. /// \b Example:
  199. /// \code
  200. /// chaiscript::Type_Info ti = chaiscript::user_type<int>();
  201. /// \endcode
  202. template<typename T>
  203. constexpr Type_Info user_type()
  204. {
  205. return detail::Get_Type_Info<T>::get();
  206. }
  207. }
  208. #endif