Variant.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #ifndef ANKI_UTIL_VARIANT_H
  2. #define ANKI_UTIL_VARIANT_H
  3. #include "anki/util/Visitor.h"
  4. #include "anki/util/Exception.h"
  5. #include <iosfwd>
  6. #include <memory>
  7. namespace anki {
  8. /// @addtogroup util
  9. /// @{
  10. /// @addtogroup patterns
  11. /// @{
  12. // Forwards
  13. template<typename Data, typename VariantBase>
  14. class VariantDerived;
  15. template<typename... Types>
  16. class VariantBase;
  17. /// The variant base class
  18. template<typename... Types>
  19. class VariantBase:
  20. public Visitable<VariantDerived<Types, VariantBase<Types...>>...>
  21. {
  22. public:
  23. typedef Visitable<VariantDerived<Types, VariantBase<Types...>>...> Base;
  24. typedef VariantBase<Types...> Self;
  25. typedef typename BaseType::ConstVisitor ConstVisitor;
  26. typedef typename BaseType::MutableVisitor MutableVisitor;
  27. static const int TEMPLATE_PARAMETERS_NUM = sizeof...(Types);
  28. /// Default constructor
  29. VariantBase(int typeId_)
  30. : typeId(typeId_)
  31. {}
  32. virtual ~VariantBase()
  33. {}
  34. uint getTypeId() const
  35. {
  36. return typeId;
  37. }
  38. /// Get the parameter's value. It throws if the @a Data is incompatible
  39. template<typename Data>
  40. const Data& get() const
  41. {
  42. checkValue<Data>();
  43. return static_cast<const VariantDerived<Data, SelfType>&>(*this).get();
  44. }
  45. /// Generic setter. It throws if the @a Data is incompatible
  46. template<typename Data>
  47. void set(const Data& x)
  48. {
  49. checkValue<Data>();
  50. static_cast<VariantDerived<Data, SelfType>&>(*this).set(x);
  51. }
  52. /// Compare the derived classes
  53. virtual bool equal(const SelfType& b) const = 0;
  54. /// Copy the derived classes
  55. virtual void copy(const SelfType& b) = 0;
  56. /// Check if two derived are the same type
  57. bool areSameType(const SelfType& b) const
  58. {
  59. return typeId == b.typeId;
  60. }
  61. /// Print
  62. friend std::ostream& operator<<(std::ostream& s, const SelfType& x)
  63. {
  64. PrintVisitor v(s);
  65. x.accept(v);
  66. return s;
  67. }
  68. protected:
  69. static constexpr char* INCOMPATIBLES_ERR = "Incompatible parameter types";
  70. private:
  71. template<typename... Types_>
  72. struct PrintVisitor;
  73. template<typename First, typename... Types_>
  74. struct PrintVisitor<First, Types_...>: PrintVisitor<Types_...>
  75. {
  76. PrintVisitor(std::ostream& stream)
  77. : PrintVisitor<Types_...>(stream)
  78. {}
  79. void visit(const First& x)
  80. {
  81. PrintVisitor<Types_...>::stream << x;
  82. }
  83. };
  84. template<typename First>
  85. struct PrintVisitor<First>: ConstVisitorType
  86. {
  87. std::ostream& stream;
  88. PrintVisitor(std::ostream& stream_)
  89. : stream(stream_)
  90. {}
  91. void visit(const First& x)
  92. {
  93. stream << x;
  94. }
  95. };
  96. using PrintVisitor = PrintVisitor<VariantDerived<Types, SelfType>...>;
  97. uint typeId; ///< type ID
  98. /// Use const struff to check if @a Data is compatible with this
  99. template<typename Data>
  100. void checkValue() const
  101. {
  102. typedef VariantDerived<Data, SelfType> Vd;
  103. const int id = BaseType::template getTypeId<Vd>();
  104. if(id != typeId)
  105. {
  106. throw ANKI_EXCEPTION(INCOMPATIBLES_ERR);
  107. }
  108. }
  109. };
  110. /// VariantDerived template class. Using the @a TData and the @a TVariantBase
  111. /// it constructs a variant class
  112. template<typename TData, typename TVariantBase>
  113. class VariantDerived: public TVariantBase
  114. {
  115. public:
  116. typedef TData Data;
  117. typedef TVariantBase Base;
  118. typedef VariantDerived<DataType, BaseType> Self;
  119. typedef typename BaseType::ConstVisitor ConstVisitor;
  120. typedef typename BaseType::MutableVisitor MutableVisitor;
  121. static const int TYPE_ID =
  122. BaseType::BaseType::template getTypeId<SelfType>();
  123. /// Constructor
  124. VariantDerived()
  125. : BaseType(TYPE_ID), data(DataType())
  126. {}
  127. /// Constructor
  128. VariantDerived(const DataType& x)
  129. : BaseType(TYPE_ID), data(x)
  130. {}
  131. /// Copy constructor
  132. VariantDerived(const SelfType& b)
  133. : BaseType(TYPE_ID), data(b.data)
  134. {}
  135. /// @name Accessors
  136. /// @{
  137. void set(const DataType& x)
  138. {
  139. data = x;
  140. }
  141. const DataType& get() const
  142. {
  143. return data;
  144. }
  145. /// @}
  146. /// Compare
  147. bool operator==(const SelfType& b) const
  148. {
  149. return data == b.data;
  150. }
  151. /// Implements the VariantBase::equal
  152. bool equal(const BaseType& b) const
  153. {
  154. if(!BaseType::areSameType(b))
  155. {
  156. throw ANKI_EXCEPTION(BaseType::INCOMPATIBLES_ERR);
  157. }
  158. return *this == static_cast<const SelfType&>(b);
  159. }
  160. /// Implements the VariantBase::copy
  161. void copy(const BaseType& b)
  162. {
  163. if(!BaseType::areSameType(b))
  164. {
  165. throw ANKI_EXCEPTION(BaseType::INCOMPATIBLES_ERR);
  166. }
  167. data = static_cast<const SelfType&>(b).data;
  168. }
  169. /// Implements VariantBase::accept
  170. void accept(ConstVisitorType& v) const
  171. {
  172. v.visit(*this);
  173. }
  174. /// Implements VariantBase::accept
  175. void accept(MutableVisitorType& v)
  176. {
  177. v.visit(*this);
  178. }
  179. /// Print
  180. friend std::ostream& operator<<(std::ostream& s, const SelfType& x)
  181. {
  182. s << x.data;
  183. return s;
  184. }
  185. private:
  186. DataType data; ///< The data
  187. };
  188. /// XXX
  189. /// @note It is no possible to have default constructor because we cannot have
  190. /// template default constructor
  191. template<typename... Types>
  192. class Variant
  193. {
  194. public:
  195. typedef Variant<Types...> SelfType;
  196. typedef VariantBase<Types...> VariantBaseType;
  197. /// Default constructor
  198. Variant()
  199. {}
  200. /// Constructor with data
  201. template<typename Data>
  202. explicit Variant(const Data& x)
  203. : ptr(new VariantDerived<Data, VariantBaseType>(x))
  204. {}
  205. /// Copy constructor
  206. Variant(const SelfType& x)
  207. {
  208. CopyVisitorType v(*this);
  209. x.ptr->accept(v);
  210. }
  211. ~Variant()
  212. {}
  213. /// Get the parameter's value. It throws if the @a Data is incompatible
  214. template<typename Data>
  215. const Data& get() const
  216. {
  217. return ptr->get<Data>();
  218. }
  219. /// Generic setter. It throws if the @a Data is incompatible
  220. template<typename Data>
  221. void set(const Data& x)
  222. {
  223. ptr->set<Data>(x);
  224. }
  225. /// Copy
  226. SelfType& operator=(const SelfType& b)
  227. {
  228. ptr->copy(*b.ptr);
  229. return *this;
  230. }
  231. /// Compare
  232. bool operator==(const SelfType& b) const
  233. {
  234. return ptr->equal(*b.ptr);
  235. }
  236. /// set value
  237. template<typename Data>
  238. SelfType& operator=(const Data& b)
  239. {
  240. set<Data>(b);
  241. return *this;
  242. }
  243. friend std::ostream& operator<<(std::ostream& s, const SelfType& x)
  244. {
  245. s << *x.ptr;
  246. return s;
  247. }
  248. private:
  249. // Forward
  250. template<typename... Types_>
  251. struct CopyVisitor;
  252. /// Visitor used to copy the data of a VariantBase to a Variant
  253. template<typename First, typename... Types_>
  254. struct CopyVisitor<First, Types_...>: CopyVisitor<Types_...>
  255. {
  256. using CopyVisitor<Types_...>::visit;
  257. CopyVisitor(SelfType& a)
  258. : CopyVisitor<Types_...>(a)
  259. {}
  260. void visit(const First& b)
  261. {
  262. CopyVisitor<Types_...>::a.ptr.reset(new First(b.get()));
  263. }
  264. };
  265. // Specialized for one
  266. template<typename First>
  267. struct CopyVisitor<First>: VariantBaseType::ConstVisitorType
  268. {
  269. SelfType& a;
  270. CopyVisitor(SelfType& a_)
  271. : a(a_)
  272. {}
  273. void visit(const First& b)
  274. {
  275. a.ptr.reset(new First(b.get()));
  276. }
  277. };
  278. typedef CopyVisitor<VariantDerived<Types, VariantBaseType>...>
  279. CopyVisitorType;
  280. /// The only data member, a pointer to a VariantBase class
  281. std::unique_ptr<VariantBaseType> ptr;
  282. };
  283. /// @}
  284. /// @}
  285. } // end namespace anki
  286. #endif