Visitor.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. /// @file
  6. /// The file contains visitor concepts
  7. ///
  8. /// @par The main classes are:
  9. /// @li Visitable: For non related types
  10. /// @li VisitableCommonBase: For types with common base
  11. #pragma once
  12. #include <AnKi/Util/Assert.h>
  13. #include <AnKi/Util/Array.h>
  14. #include <AnKi/Util/StdTypes.h>
  15. namespace anki {
  16. /// @addtogroup util_patterns
  17. /// @{
  18. /// Namespace for visitor internal classes
  19. namespace visitor_detail {
  20. /// A smart struct that given a type and a list of types finds a const integer indicating the type's position from the
  21. /// back of the list.
  22. ///
  23. /// Example of usage:
  24. /// @code
  25. /// GetVariadicTypeId<int, float, std::string>::get<float>() == 1
  26. /// GetVariadicTypeId<int, float, std::string>::get<int>() == 0
  27. /// GetVariadicTypeId<int, float, std::string>::get<char>() // Compiler error
  28. /// @endcode
  29. template<typename... Types>
  30. struct GetVariadicTypeId
  31. {
  32. // Forward
  33. template<typename Type, typename... Types_>
  34. struct Helper;
  35. // Declaration
  36. template<typename Type, typename TFirst, typename... Types_>
  37. struct Helper<Type, TFirst, Types_...> : Helper<Type, Types_...>
  38. {
  39. };
  40. // Specialized
  41. template<typename Type, typename... Types_>
  42. struct Helper<Type, Type, Types_...>
  43. {
  44. static const I ID = sizeof...(Types_);
  45. };
  46. /// Get the id
  47. template<typename Type>
  48. static constexpr I get()
  49. {
  50. return sizeof...(Types) - Helper<Type, Types...>::ID - 1;
  51. }
  52. };
  53. /// A struct that from a variadic arguments list it returnes the type using an ID.
  54. /// Example of usage:
  55. /// @code
  56. /// GetTypeUsingId<std::string, int, float>::DataType<0> x = "a string";
  57. /// GetTypeUsingId<std::string, int, float>::DataType<1> y = 123;
  58. /// GetTypeUsingId<std::string, int, float>::DataType<2> y = 123.456f;
  59. /// @endcode
  60. template<typename... Types>
  61. struct GetTypeUsingId
  62. {
  63. // Forward declaration
  64. template<I id, typename... Types_>
  65. struct Helper;
  66. // Declaration
  67. template<I id, typename TFirst, typename... Types_>
  68. struct Helper<id, TFirst, Types_...> : Helper<id - 1, Types_...>
  69. {
  70. };
  71. // Specialized
  72. template<typename TFirst, typename... Types_>
  73. struct Helper<0, TFirst, Types_...>
  74. {
  75. using DataType = TFirst;
  76. };
  77. template<I id>
  78. using DataType = typename Helper<id, Types...>::DataType;
  79. };
  80. } // end namespace visitor_detail
  81. /// Visitable class
  82. template<typename... Types>
  83. class Visitable
  84. {
  85. public:
  86. Visitable()
  87. {
  88. }
  89. template<typename T>
  90. Visitable(T* t)
  91. {
  92. setupVisitable(t);
  93. }
  94. I getVisitableTypeId() const
  95. {
  96. return m_what;
  97. }
  98. template<typename T>
  99. static constexpr I getVariadicTypeId()
  100. {
  101. return visitor_detail::GetVariadicTypeId<Types...>::template get<T>();
  102. }
  103. /// Apply visitor
  104. template<typename TVisitor>
  105. void acceptVisitor(TVisitor& v)
  106. {
  107. ANKI_ASSERT(m_what != -1 && address != nullptr);
  108. acceptVisitorInternal<TVisitor, Types...>(v);
  109. }
  110. /// Apply visitor (const version)
  111. template<typename TVisitor>
  112. void acceptVisitor(TVisitor& v) const
  113. {
  114. ANKI_ASSERT(m_what != -1 && address != nullptr);
  115. acceptVisitorInternalConst<TVisitor, Types...>(v);
  116. }
  117. /// Setup the data
  118. template<typename T>
  119. void setupVisitable(T* t)
  120. {
  121. // Null arg. Setting for second time? Now allowed
  122. ANKI_ASSERT(t != nullptr);
  123. ANKI_ASSERT(address == nullptr && m_what == -1);
  124. address = t;
  125. m_what = visitor_detail::GetVariadicTypeId<Types...>::template get<T>();
  126. }
  127. private:
  128. I m_what = -1; ///< The type ID
  129. void* address = nullptr; ///< The address to the data
  130. /// @name Accept visitor template methods
  131. /// @{
  132. template<typename TVisitor, typename TFirst>
  133. void acceptVisitorInternal(TVisitor& v)
  134. {
  135. switch(m_what)
  136. {
  137. case 0:
  138. v.template visit(*reinterpret_cast<TFirst*>(address));
  139. break;
  140. default:
  141. ANKI_ASSERT(0 && "Wrong type ID");
  142. break;
  143. }
  144. }
  145. template<typename TVisitor, typename TFirst, typename TSecond, typename... Types_>
  146. void acceptVisitorInternal(TVisitor& v)
  147. {
  148. constexpr I i = sizeof...(Types) - sizeof...(Types_) - 1;
  149. switch(m_what)
  150. {
  151. case i:
  152. v.template visit(*reinterpret_cast<TSecond*>(address));
  153. break;
  154. default:
  155. acceptVisitorInternal<TVisitor, TFirst, Types_...>(v);
  156. break;
  157. }
  158. }
  159. template<typename TVisitor, typename TFirst>
  160. void acceptVisitorInternalConst(TVisitor& v) const
  161. {
  162. switch(m_what)
  163. {
  164. case 0:
  165. v.template visit(*reinterpret_cast<const TFirst*>(address));
  166. break;
  167. default:
  168. ANKI_ASSERT(0 && "Wrong type ID");
  169. break;
  170. }
  171. }
  172. template<typename TVisitor, typename TFirst, typename TSecond, typename... Types_>
  173. void acceptVisitorInternalConst(TVisitor& v) const
  174. {
  175. constexpr I i = sizeof...(Types) - sizeof...(Types_) - 1;
  176. switch(m_what)
  177. {
  178. case i:
  179. v.template visit(*reinterpret_cast<const TSecond*>(address));
  180. break;
  181. default:
  182. acceptVisitorInternalConst<TVisitor, TFirst, Types_...>(v);
  183. break;
  184. }
  185. }
  186. /// @}
  187. };
  188. /// Visitable for types with common base
  189. /// @tparam TBase The base class
  190. /// @tparam Types The types that compose the visitable. They are derived from TBase
  191. ///
  192. /// @note In debug mode it uses dynamic cast as an extra protection reason
  193. template<typename TBase, typename... Types>
  194. class VisitableCommonBase
  195. {
  196. public:
  197. #if ANKI_EXTRA_CHECKS
  198. // Allow dynamic cast in acceptVisitor
  199. virtual ~VisitableCommonBase()
  200. {
  201. }
  202. #endif
  203. I getVisitableTypeId() const
  204. {
  205. ANKI_ASSERT(m_what != -1);
  206. return m_what;
  207. }
  208. template<typename T>
  209. static constexpr I getVariadicTypeId()
  210. {
  211. return visitor_detail::GetVariadicTypeId<Types...>::template get<T>();
  212. }
  213. /// Check if this is of type
  214. template<typename T>
  215. Bool isTypeOf() const
  216. {
  217. return getVariadicTypeId<T>() == getVisitableTypeId();
  218. }
  219. /// Apply mutable visitor
  220. template<typename TVisitor>
  221. Error acceptVisitor(TVisitor& v)
  222. {
  223. ANKI_ASSERT(m_what != -1);
  224. return acceptVisitorInternal<TVisitor, Types...>(v);
  225. }
  226. /// Apply const visitor
  227. template<typename TVisitor>
  228. Error acceptVisitor(TVisitor& v) const
  229. {
  230. ANKI_ASSERT(m_what != -1);
  231. return acceptVisitorInternalConst<TVisitor, Types...>(v);
  232. }
  233. /// Setup the type ID
  234. template<typename T>
  235. void setupVisitable(const T*)
  236. {
  237. ANKI_ASSERT(m_what == -1); // Setting for second time not allowed
  238. m_what = visitor_detail::GetVariadicTypeId<Types...>::template get<T>();
  239. }
  240. private:
  241. I m_what = -1; ///< The type ID
  242. /// @name Accept visitor template methods
  243. /// @{
  244. template<typename TVisitor, typename TFirst>
  245. Error acceptVisitorInternal(TVisitor& v)
  246. {
  247. Error err = Error::kNone;
  248. switch(m_what)
  249. {
  250. case 0:
  251. {
  252. #if ANKI_EXTRA_CHECKS
  253. TFirst* base = dynamic_cast<TFirst*>(this);
  254. ANKI_ASSERT(base != nullptr);
  255. #else
  256. TFirst* base = static_cast<TFirst*>(this);
  257. #endif
  258. err = v.template visit(*base);
  259. }
  260. break;
  261. default:
  262. ANKI_ASSERT(0 && "Wrong type ID");
  263. break;
  264. }
  265. return err;
  266. }
  267. template<typename TVisitor, typename TFirst, typename TSecond, typename... Types_>
  268. Error acceptVisitorInternal(TVisitor& v)
  269. {
  270. Error err = Error::kNone;
  271. constexpr I i = sizeof...(Types) - sizeof...(Types_) - 1;
  272. switch(m_what)
  273. {
  274. case i:
  275. {
  276. #if ANKI_EXTRA_CHECKS
  277. TSecond* base = dynamic_cast<TSecond*>(this);
  278. ANKI_ASSERT(base != nullptr);
  279. #else
  280. TSecond* base = static_cast<TSecond*>(this);
  281. #endif
  282. err = v.template visit(*base);
  283. }
  284. break;
  285. default:
  286. err = acceptVisitorInternal<TVisitor, TFirst, Types_...>(v);
  287. break;
  288. }
  289. return err;
  290. }
  291. template<typename TVisitor, typename TFirst>
  292. Error acceptVisitorInternalConst(TVisitor& v) const
  293. {
  294. Error err = Error::kNone;
  295. switch(m_what)
  296. {
  297. case 0:
  298. {
  299. #if ANKI_EXTRA_CHECKS
  300. const TFirst* base = dynamic_cast<const TFirst*>(this);
  301. ANKI_ASSERT(base != nullptr);
  302. #else
  303. const TFirst* base = static_cast<const TFirst*>(this);
  304. #endif
  305. err = v.template visit(*base);
  306. break;
  307. }
  308. default:
  309. ANKI_ASSERT(0 && "Wrong type ID");
  310. break;
  311. }
  312. return err;
  313. }
  314. template<typename TVisitor, typename TFirst, typename TSecond, typename... Types_>
  315. Error acceptVisitorInternalConst(TVisitor& v) const
  316. {
  317. Error err = Error::kNone;
  318. constexpr I i = sizeof...(Types) - sizeof...(Types_) - 1;
  319. switch(m_what)
  320. {
  321. case i:
  322. {
  323. #if ANKI_EXTRA_CHECKS
  324. const TSecond* base = dynamic_cast<const TSecond*>(this);
  325. ANKI_ASSERT(base != nullptr);
  326. #else
  327. const TSecond* base = static_cast<const TSecond*>(this);
  328. #endif
  329. err = v.template visit(*base);
  330. break;
  331. }
  332. default:
  333. err = acceptVisitorInternalConst<TVisitor, TFirst, Types_...>(v);
  334. break;
  335. }
  336. return err;
  337. }
  338. /// @}
  339. };
  340. /// @}
  341. } // end namespace anki