boxed_cast_helper.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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_BOXED_CAST_HELPER_HPP_
  9. #define CHAISCRIPT_BOXED_CAST_HELPER_HPP_
  10. #include <memory>
  11. #include <type_traits>
  12. #include "boxed_value.hpp"
  13. #include "type_info.hpp"
  14. namespace chaiscript
  15. {
  16. class Type_Conversions_State;
  17. namespace detail
  18. {
  19. // Cast_Helper_Inner helper classes
  20. template<typename T>
  21. T* throw_if_null(T *t)
  22. {
  23. if (t) { return t; }
  24. throw std::runtime_error("Attempted to dereference null Boxed_Value");
  25. }
  26. template<typename T>
  27. static const T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
  28. if (ob.get_type_info() == ti) {
  29. return ptr;
  30. } else {
  31. throw chaiscript::detail::exception::bad_any_cast();
  32. }
  33. }
  34. template<typename T>
  35. static T *verify_type_no_throw(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
  36. if (!ob.is_const() && ob.get_type_info() == ti) {
  37. return ptr;
  38. } else {
  39. throw chaiscript::detail::exception::bad_any_cast();
  40. }
  41. }
  42. template<typename T>
  43. static const T *verify_type(const Boxed_Value &ob, const std::type_info &ti, const T *ptr) {
  44. if (ob.get_type_info().bare_equal_type_info(ti)) {
  45. return throw_if_null(ptr);
  46. } else {
  47. throw chaiscript::detail::exception::bad_any_cast();
  48. }
  49. }
  50. template<typename T>
  51. static T *verify_type(const Boxed_Value &ob, const std::type_info &ti, T *ptr) {
  52. if (!ob.is_const() && ob.get_type_info().bare_equal_type_info(ti)) {
  53. return throw_if_null(ptr);
  54. } else {
  55. throw chaiscript::detail::exception::bad_any_cast();
  56. }
  57. }
  58. /// Generic Cast_Helper_Inner, for casting to any type
  59. template<typename Result>
  60. struct Cast_Helper_Inner
  61. {
  62. static Result cast(const Boxed_Value &ob, const Type_Conversions_State *)
  63. {
  64. return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
  65. }
  66. };
  67. template<typename Result>
  68. struct Cast_Helper_Inner<const Result> : Cast_Helper_Inner<Result>
  69. {
  70. };
  71. /// Cast_Helper_Inner for casting to a const * type
  72. template<typename Result>
  73. struct Cast_Helper_Inner<const Result *>
  74. {
  75. static const Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
  76. {
  77. return static_cast<const Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_const_ptr()));
  78. }
  79. };
  80. /// Cast_Helper_Inner for casting to a * type
  81. template<typename Result>
  82. struct Cast_Helper_Inner<Result *>
  83. {
  84. static Result * cast(const Boxed_Value &ob, const Type_Conversions_State *)
  85. {
  86. return static_cast<Result *>(verify_type_no_throw(ob, typeid(Result), ob.get_ptr()));
  87. }
  88. };
  89. template<typename Result>
  90. struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
  91. {
  92. };
  93. template<typename Result>
  94. struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
  95. {
  96. };
  97. /// Cast_Helper_Inner for casting to a & type
  98. template<typename Result>
  99. struct Cast_Helper_Inner<const Result &>
  100. {
  101. static const Result & cast(const Boxed_Value &ob, const Type_Conversions_State *)
  102. {
  103. return *static_cast<const Result *>(verify_type(ob, typeid(Result), ob.get_const_ptr()));
  104. }
  105. };
  106. /// Cast_Helper_Inner for casting to a & type
  107. template<typename Result>
  108. struct Cast_Helper_Inner<Result &>
  109. {
  110. static Result& cast(const Boxed_Value &ob, const Type_Conversions_State *)
  111. {
  112. return *static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr()));
  113. }
  114. };
  115. /// Cast_Helper_Inner for casting to a && type
  116. template<typename Result>
  117. struct Cast_Helper_Inner<Result &&>
  118. {
  119. static Result&& cast(const Boxed_Value &ob, const Type_Conversions_State *)
  120. {
  121. return std::move(*static_cast<Result *>(verify_type(ob, typeid(Result), ob.get_ptr())));
  122. }
  123. };
  124. /// Cast_Helper_Inner for casting to a std::unique_ptr<> && type
  125. /// \todo Fix the fact that this has to be in a shared_ptr for now
  126. template<typename Result>
  127. struct Cast_Helper_Inner<std::unique_ptr<Result> &&>
  128. {
  129. static std::unique_ptr<Result> &&cast(const Boxed_Value &ob, const Type_Conversions_State *)
  130. {
  131. return std::move(*(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>()));
  132. }
  133. };
  134. /// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
  135. /// \todo Fix the fact that this has to be in a shared_ptr for now
  136. template<typename Result>
  137. struct Cast_Helper_Inner<std::unique_ptr<Result> &>
  138. {
  139. static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
  140. {
  141. return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
  142. }
  143. };
  144. /// Cast_Helper_Inner for casting to a std::unique_ptr<> & type
  145. /// \todo Fix the fact that this has to be in a shared_ptr for now
  146. template<typename Result>
  147. struct Cast_Helper_Inner<const std::unique_ptr<Result> &>
  148. {
  149. static std::unique_ptr<Result> &cast(const Boxed_Value &ob, const Type_Conversions_State *)
  150. {
  151. return *(ob.get().cast<std::shared_ptr<std::unique_ptr<Result>>>());
  152. }
  153. };
  154. /// Cast_Helper_Inner for casting to a std::shared_ptr<> type
  155. template<typename Result>
  156. struct Cast_Helper_Inner<std::shared_ptr<Result> >
  157. {
  158. static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
  159. {
  160. return ob.get().cast<std::shared_ptr<Result> >();
  161. }
  162. };
  163. /// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
  164. template<typename Result>
  165. struct Cast_Helper_Inner<std::shared_ptr<const Result> >
  166. {
  167. static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
  168. {
  169. if (!ob.get_type_info().is_const())
  170. {
  171. return std::const_pointer_cast<const Result>(ob.get().cast<std::shared_ptr<Result> >());
  172. } else {
  173. return ob.get().cast<std::shared_ptr<const Result> >();
  174. }
  175. }
  176. };
  177. /// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
  178. template<typename Result>
  179. struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
  180. {
  181. };
  182. template<typename Result>
  183. struct Cast_Helper_Inner<const std::shared_ptr<Result> &> : Cast_Helper_Inner<std::shared_ptr<Result> >
  184. {
  185. };
  186. template<typename Result>
  187. struct Cast_Helper_Inner<std::shared_ptr<Result> &>
  188. {
  189. static_assert(!std::is_const<Result>::value, "Non-const reference to std::shared_ptr<const T> is not supported");
  190. static auto cast(const Boxed_Value &ob, const Type_Conversions_State *)
  191. {
  192. std::shared_ptr<Result> &res = ob.get().cast<std::shared_ptr<Result> >();
  193. return ob.pointer_sentinel(res);
  194. }
  195. };
  196. /// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
  197. template<typename Result>
  198. struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
  199. {
  200. };
  201. template<typename Result>
  202. struct Cast_Helper_Inner<const std::shared_ptr<const Result> &> : Cast_Helper_Inner<std::shared_ptr<const Result> >
  203. {
  204. };
  205. /// Cast_Helper_Inner for casting to a Boxed_Value type
  206. template<>
  207. struct Cast_Helper_Inner<Boxed_Value>
  208. {
  209. static Boxed_Value cast(const Boxed_Value &ob, const Type_Conversions_State *)
  210. {
  211. return ob;
  212. }
  213. };
  214. /// Cast_Helper_Inner for casting to a Boxed_Value & type
  215. template<>
  216. struct Cast_Helper_Inner<Boxed_Value &>
  217. {
  218. static std::reference_wrapper<Boxed_Value> cast(const Boxed_Value &ob, const Type_Conversions_State *)
  219. {
  220. return std::ref(const_cast<Boxed_Value &>(ob));
  221. }
  222. };
  223. /// Cast_Helper_Inner for casting to a const Boxed_Value & type
  224. template<>
  225. struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
  226. {
  227. };
  228. template<>
  229. struct Cast_Helper_Inner<const Boxed_Value &> : Cast_Helper_Inner<Boxed_Value>
  230. {
  231. };
  232. /// Cast_Helper_Inner for casting to a std::reference_wrapper type
  233. template<typename Result>
  234. struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
  235. {
  236. };
  237. template<typename Result>
  238. struct Cast_Helper_Inner<const std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
  239. {
  240. };
  241. template<typename Result>
  242. struct Cast_Helper_Inner<const std::reference_wrapper<Result> &> : Cast_Helper_Inner<Result &>
  243. {
  244. };
  245. template<typename Result>
  246. struct Cast_Helper_Inner<std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
  247. {
  248. };
  249. template<typename Result>
  250. struct Cast_Helper_Inner<const std::reference_wrapper<const Result> > : Cast_Helper_Inner<const Result &>
  251. {
  252. };
  253. template<typename Result>
  254. struct Cast_Helper_Inner<const std::reference_wrapper<const Result> & > : Cast_Helper_Inner<const Result &>
  255. {
  256. };
  257. /// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
  258. template<typename T>
  259. struct Cast_Helper
  260. {
  261. static decltype(auto) cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
  262. {
  263. return(Cast_Helper_Inner<T>::cast(ob, t_conversions));
  264. }
  265. };
  266. }
  267. }
  268. #endif