Variant.h 6.6 KB

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