variant_data_policy.h 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. /************************************************************************************
  2. * *
  3. * Copyright (c) 2014 - 2018 Axel Menzel <info@rttr.org> *
  4. * *
  5. * This file is part of RTTR (Run Time Type Reflection) *
  6. * License: MIT License *
  7. * *
  8. * Permission is hereby granted, free of charge, to any person obtaining *
  9. * a copy of this software and associated documentation files (the "Software"), *
  10. * to deal in the Software without restriction, including without limitation *
  11. * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  12. * and/or sell copies of the Software, and to permit persons to whom the *
  13. * Software is furnished to do so, subject to the following conditions: *
  14. * *
  15. * The above copyright notice and this permission notice shall be included in *
  16. * all copies or substantial portions of the Software. *
  17. * *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
  24. * SOFTWARE. *
  25. * *
  26. *************************************************************************************/
  27. #ifndef RTTR_VARIANT_DATA_POLICY_H_
  28. #define RTTR_VARIANT_DATA_POLICY_H_
  29. #include "rttr/detail/misc/misc_type_traits.h"
  30. #include "rttr/detail/variant/variant_data.h"
  31. #include "rttr/detail/misc/argument_wrapper.h"
  32. #include "rttr/detail/variant_associative_view/variant_associative_view_creator.h"
  33. #include "rttr/detail/variant_sequential_view/variant_sequential_view_creator.h"
  34. #include "rttr/detail/variant/variant_data_converter.h"
  35. #include "rttr/detail/comparison/compare_equal.h"
  36. #include "rttr/detail/comparison/compare_less.h"
  37. #include <cstdint>
  38. namespace rttr
  39. {
  40. namespace detail
  41. {
  42. template<typename T, typename Converter = empty_type_converter<T>>
  43. struct variant_data_policy_big;
  44. template<typename T, typename Converter = empty_type_converter<T>>
  45. struct variant_data_policy_small;
  46. template<typename T>
  47. struct variant_data_policy_array_small;
  48. template<typename T>
  49. struct variant_data_policy_array_big;
  50. struct void_variant_type;
  51. struct variant_data_policy_void;
  52. struct variant_data_policy_nullptr_t;
  53. struct variant_data_policy_string;
  54. template<typename T>
  55. struct variant_data_policy_arithmetic;
  56. /////////////////////////////////////////////////////////////////////////////////////////
  57. template<typename T, bool Can_Place = (sizeof(T) <= sizeof(variant_data)) &&
  58. (std::alignment_of<T>::value <= std::alignment_of<variant_data>::value)>
  59. using can_place_in_variant = std::integral_constant<bool, Can_Place>;
  60. /*!
  61. * This template alias will determine the manager class for the given type \p T which is placed inside the variant.
  62. *
  63. * Small types will be placed inside the variant without explicit allocation of memory.
  64. * This will improve the performance a lot.
  65. *
  66. * \remark Raw char arrays with rank equal to one, will be copied to a std::string.
  67. *
  68. * \return The manager class for the type T.
  69. */
  70. template<typename T>
  71. using variant_policy = conditional_t<std::is_same<T, void_variant_type>::value,
  72. variant_data_policy_void,
  73. conditional_t<is_nullptr_t<T>::value,
  74. variant_data_policy_nullptr_t,
  75. conditional_t<std::is_same<T, std::string>::value || is_one_dim_char_array<T>::value,
  76. variant_data_policy_string,
  77. conditional_t<can_place_in_variant<T>::value,
  78. conditional_t<std::is_arithmetic<T>::value,
  79. variant_data_policy_arithmetic<T>,
  80. conditional_t<std::is_array<T>::value,
  81. variant_data_policy_array_small<T>,
  82. conditional_t<std::is_enum<T>::value,
  83. variant_data_policy_small<T, default_type_converter<T, convert_from_enum<T>>>,
  84. variant_data_policy_small<T>
  85. >
  86. >
  87. >,
  88. conditional_t<std::is_array<T>::value,
  89. variant_data_policy_array_big<T>,
  90. conditional_t<std::is_enum<T>::value,
  91. variant_data_policy_big<T, default_type_converter<T, convert_from_enum<T>>>,
  92. variant_data_policy_big<T>
  93. >
  94. >
  95. >
  96. >
  97. >
  98. >;
  99. /////////////////////////////////////////////////////////////////////////////////////////
  100. /*!
  101. * \brief This enum is used in the invoke function to delegate
  102. * the execution of certain operations.
  103. *
  104. */
  105. enum class variant_policy_operation : uint8_t
  106. {
  107. DESTROY,
  108. CLONE,
  109. SWAP,
  110. EXTRACT_WRAPPED_VALUE,
  111. CREATE_WRAPPED_VALUE,
  112. GET_VALUE,
  113. GET_TYPE,
  114. GET_PTR,
  115. GET_RAW_TYPE,
  116. GET_RAW_PTR,
  117. GET_ADDRESS_CONTAINER,
  118. IS_ASSOCIATIVE_CONTAINER,
  119. IS_SEQUENTIAL_CONTAINER,
  120. CREATE_ASSOCIATIV_VIEW,
  121. CREATE_SEQUENTIAL_VIEW,
  122. IS_VALID,
  123. IS_NULLPTR,
  124. CONVERT,
  125. COMPARE_EQUAL,
  126. COMPARE_LESS
  127. };
  128. /////////////////////////////////////////////////////////////////////////////////////////
  129. using variant_policy_func = bool (*)(variant_policy_operation, const variant_data&, argument_wrapper);
  130. /////////////////////////////////////////////////////////////////////////////////////////
  131. #define COMPARE_EQUAL_PRE_PROC(lhs, rhs, ok) \
  132. compare_equal(Tp::get_value(src_data), rhs.get_value<T>(), ok)
  133. #define COMPARE_LESS_PRE_PROC(lhs, rhs, result) \
  134. compare_less_than(Tp::get_value(src_data), rhs.get_value<T>(), result)
  135. /////////////////////////////////////////////////////////////////////////////////////////
  136. template<typename T>
  137. enable_if_t<std::is_pointer<T>::value, bool>
  138. static RTTR_INLINE is_nullptr(T& val)
  139. {
  140. return (val == nullptr);
  141. }
  142. /////////////////////////////////////////////////////////////////////////////////////////
  143. template<typename T>
  144. enable_if_t<!std::is_pointer<T>::value, bool>
  145. static RTTR_INLINE is_nullptr(T& to)
  146. {
  147. return false;
  148. }
  149. /////////////////////////////////////////////////////////////////////////////////////////
  150. /////////////////////////////////////////////////////////////////////////////////////////
  151. template<typename T>
  152. using is_copyable = std::is_copy_constructible<T>;
  153. template<typename T, typename Tp = decay_except_array_t<wrapper_mapper_t<T>> >
  154. enable_if_t<is_copyable<Tp>::value &&
  155. is_wrapper<T>::value, variant> get_wrapped_value(T& value)
  156. {
  157. using raw_wrapper_type = remove_cv_t<remove_reference_t<T>>;
  158. return variant(wrapper_mapper<raw_wrapper_type>::get(value));
  159. }
  160. /////////////////////////////////////////////////////////////////////////////////////////
  161. template<typename T, typename Tp = decay_except_array_t<wrapper_mapper_t<T>>>
  162. enable_if_t<!is_copyable<Tp>::value ||
  163. !is_wrapper<T>::value, variant> get_wrapped_value(T& value)
  164. {
  165. return variant();
  166. }
  167. /////////////////////////////////////////////////////////////////////////////////////////
  168. /*!
  169. * This class represents the base implementation for variant_data policy.
  170. *
  171. * We use the C++ idiom CRTP (Curiously Recurring Template Pattern) to avoid rewriting the same code over an over again.
  172. * The template parameter \p Tp represents the derived class, which will be invoked.
  173. * Hopefully, the function call to derived class will be inlined.
  174. */
  175. template<typename T, typename Tp, typename Converter>
  176. struct variant_data_base_policy
  177. {
  178. static bool invoke(variant_policy_operation op, const variant_data& src_data, argument_wrapper arg)
  179. {
  180. switch (op)
  181. {
  182. case variant_policy_operation::DESTROY:
  183. {
  184. Tp::destroy(const_cast<T&>(Tp::get_value(src_data)));
  185. break;
  186. }
  187. case variant_policy_operation::CLONE:
  188. {
  189. Tp::clone(Tp::get_value(src_data), arg.get_value<variant_data>());
  190. break;
  191. }
  192. case variant_policy_operation::SWAP:
  193. {
  194. Tp::swap(const_cast<T&>(Tp::get_value(src_data)), arg.get_value<variant_data>());
  195. break;
  196. }
  197. case variant_policy_operation::EXTRACT_WRAPPED_VALUE:
  198. {
  199. arg.get_value<variant>() = get_wrapped_value(Tp::get_value(src_data));
  200. break;
  201. }
  202. case variant_policy_operation::CREATE_WRAPPED_VALUE:
  203. {
  204. const auto& params = arg.get_value<std::tuple<variant&, const type&>>();
  205. variant& var = std::get<0>(params);
  206. const type& wrapper_type = std::get<1>(params);
  207. wrapper_type.create_wrapped_value(Tp::get_value(src_data), var);
  208. break;
  209. }
  210. case variant_policy_operation::GET_VALUE:
  211. {
  212. arg.get_value<const void*>() = &Tp::get_value(src_data);
  213. break;
  214. }
  215. case variant_policy_operation::GET_TYPE:
  216. {
  217. arg.get_value<type>() = type::get<T>();
  218. break;
  219. }
  220. case variant_policy_operation::GET_PTR:
  221. {
  222. arg.get_value<void*>() = as_void_ptr(std::addressof(Tp::get_value(src_data)));
  223. break;
  224. }
  225. case variant_policy_operation::GET_RAW_TYPE:
  226. {
  227. arg.get_value<type>() = type::get<typename raw_type<T>::type>();
  228. break;
  229. }
  230. case variant_policy_operation::GET_RAW_PTR:
  231. {
  232. arg.get_value<void*>() = as_void_ptr(raw_addressof(Tp::get_value(src_data)));
  233. break;
  234. }
  235. case variant_policy_operation::GET_ADDRESS_CONTAINER:
  236. {
  237. data_address_container& data = arg.get_value<data_address_container>();
  238. data.m_type = type::get< raw_addressof_return_type_t<T> >();
  239. data.m_wrapped_type = type::get< wrapper_address_return_type_t<T> >();
  240. data.m_data_address = as_void_ptr(raw_addressof(Tp::get_value(src_data)));
  241. data.m_data_address_wrapped_type = as_void_ptr(wrapped_raw_addressof(Tp::get_value(src_data)));
  242. break;
  243. }
  244. case variant_policy_operation::IS_ASSOCIATIVE_CONTAINER:
  245. {
  246. return can_create_associative_view<T>::value;
  247. }
  248. case variant_policy_operation::IS_SEQUENTIAL_CONTAINER:
  249. {
  250. return can_create_sequential_view<T>::value;
  251. }
  252. case variant_policy_operation::CREATE_ASSOCIATIV_VIEW:
  253. {
  254. arg.get_value<variant_associative_view_private&>() = create_variant_associative_view(const_cast<T&>(Tp::get_value(src_data)));
  255. break;
  256. }
  257. case variant_policy_operation::CREATE_SEQUENTIAL_VIEW:
  258. {
  259. arg.get_value<variant_sequential_view_private&>() = create_variant_sequential_view(const_cast<T&>(Tp::get_value(src_data)));
  260. break;
  261. }
  262. case variant_policy_operation::CONVERT:
  263. {
  264. return Converter::convert_to(Tp::get_value(src_data), arg.get_value<argument>());
  265. }
  266. case variant_policy_operation::IS_VALID:
  267. {
  268. return true;
  269. }
  270. case variant_policy_operation::IS_NULLPTR:
  271. {
  272. return is_nullptr(Tp::get_value(src_data));
  273. }
  274. case variant_policy_operation::COMPARE_EQUAL:
  275. {
  276. const auto& param = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
  277. const variant& lhs = std::get<0>(param);
  278. const variant& rhs = std::get<1>(param);
  279. bool& ok = std::get<2>(param);
  280. const type rhs_type = rhs.get_type();
  281. const type lhs_type = type::get<T>();
  282. const auto is_lhs_arithmetic = std::is_arithmetic<T>::value;
  283. RTTR_BEGIN_DISABLE_CONDITIONAL_EXPR_WARNING
  284. if (lhs_type == rhs_type)
  285. {
  286. return COMPARE_EQUAL_PRE_PROC(src_data, rhs, ok);
  287. }
  288. else
  289. {
  290. if (is_lhs_arithmetic && rhs_type.is_arithmetic())
  291. {
  292. return variant_compare_equal(lhs, lhs_type, rhs, rhs_type, ok);
  293. }
  294. else
  295. {
  296. variant var_tmp;
  297. if (rhs.convert(lhs_type, var_tmp))
  298. return COMPARE_EQUAL_PRE_PROC(src_data, var_tmp, ok);
  299. else if (lhs.convert(rhs_type, var_tmp))
  300. return (var_tmp.compare_equal(rhs, ok));
  301. else if (rhs.is_nullptr())
  302. return is_nullptr(Tp::get_value(src_data));
  303. }
  304. }
  305. RTTR_END_DISABLE_CONDITIONAL_EXPR_WARNING
  306. return false;
  307. }
  308. case variant_policy_operation::COMPARE_LESS:
  309. {
  310. const auto& param = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
  311. const variant& lhs = std::get<0>(param);
  312. const variant& rhs = std::get<1>(param);
  313. bool& ok = std::get<2>(param);
  314. const type rhs_type = rhs.get_type();
  315. const type lhs_type = type::get<T>();
  316. int result = 0;
  317. if (lhs_type == rhs_type)
  318. {
  319. if ((ok = COMPARE_LESS_PRE_PROC(src_data, rhs, result)) == true)
  320. return (result == -1 ? true : false);
  321. }
  322. else
  323. {
  324. return variant_compare_less(lhs, lhs_type, rhs, rhs_type, ok);
  325. }
  326. bool ok1 = false;
  327. bool ok2 = false;
  328. auto ret = (lhs.to_string(&ok1) < rhs.to_string(&ok2));
  329. if (ok1 && ok2)
  330. {
  331. ok = true;
  332. return ret;
  333. }
  334. else
  335. {
  336. return false;
  337. }
  338. }
  339. }
  340. return true;
  341. }
  342. };
  343. /////////////////////////////////////////////////////////////////////////////////////////
  344. /*!
  345. * This policy is used for small custom data types.
  346. *
  347. * These are types which will fit into the storage of \ref variant_data.
  348. * The data will be placed with "placement new" inside the variant.
  349. * That also means the destructor will be called explicitly.
  350. */
  351. template<typename T, typename Converter>
  352. struct variant_data_policy_small : variant_data_base_policy<T, variant_data_policy_small<T>, Converter>
  353. {
  354. static RTTR_INLINE const T& get_value(const variant_data& data)
  355. {
  356. return reinterpret_cast<const T&>(data);
  357. }
  358. static RTTR_INLINE void destroy(T& value)
  359. {
  360. value.~T();
  361. }
  362. static RTTR_INLINE void clone(const T& value, variant_data& dest)
  363. {
  364. new (&dest) T(value);
  365. }
  366. static RTTR_INLINE void swap(T& value, variant_data& dest)
  367. {
  368. new (&dest) T(value);
  369. destroy(value);
  370. }
  371. template<typename U>
  372. static RTTR_INLINE void create(U&& value, variant_data& dest)
  373. {
  374. new (&dest) T(std::forward<U>(value));
  375. }
  376. };
  377. /////////////////////////////////////////////////////////////////////////////////////////
  378. /*!
  379. * This policy is used for custom types that size does NOT fit into variant_data.
  380. *
  381. * Then the type will be allocated on the heap and a pointer to the data is stored in variant_data.
  382. */
  383. template<typename T, typename Converter>
  384. struct variant_data_policy_big : variant_data_base_policy<T, variant_data_policy_big<T>, Converter>
  385. {
  386. static RTTR_INLINE const T& get_value(const variant_data& data)
  387. {
  388. return *reinterpret_cast<T* const &>(data);
  389. }
  390. static RTTR_INLINE void destroy(T& value)
  391. {
  392. delete &value;
  393. }
  394. RTTR_BEGIN_DISABLE_INIT_LIST_WARNING
  395. static RTTR_INLINE void clone(const T& value, variant_data& dest)
  396. {
  397. reinterpret_cast<T*&>(dest) = new T(value);
  398. }
  399. static RTTR_INLINE void swap(T& value, variant_data& dest)
  400. {
  401. reinterpret_cast<T*&>(dest) = &value;
  402. }
  403. template<typename U>
  404. static RTTR_INLINE void create(U&& value, variant_data& dest)
  405. {
  406. reinterpret_cast<T*&>(dest) = new T(std::forward<U>(value));
  407. }
  408. RTTR_END_DISABLE_INIT_LIST_WARNING
  409. };
  410. /////////////////////////////////////////////////////////////////////////////////////////
  411. #define COPY_ARRAY_PRE_PROC(value, dest) \
  412. copy_array(value, const_cast<typename std::remove_const<T>::type&>(get_value(dest)));
  413. /*!
  414. * This policy is used for small raw array types, which fit in \p variant_data.
  415. *
  416. * The array data will be copied into \p variant_data.
  417. */
  418. template<typename T>
  419. struct variant_data_policy_array_small : variant_data_base_policy<T, variant_data_policy_array_small<T>>
  420. {
  421. static RTTR_INLINE const T& get_value(const variant_data& data)
  422. {
  423. return reinterpret_cast<const T&>(data);
  424. }
  425. static RTTR_INLINE void destroy(T& value)
  426. {
  427. }
  428. static RTTR_INLINE void clone(const T& value, variant_data& dest)
  429. {
  430. COPY_ARRAY_PRE_PROC(value, dest);
  431. }
  432. static RTTR_INLINE void swap(T& value, variant_data& dest)
  433. {
  434. clone(value, dest);
  435. }
  436. template<typename U>
  437. static RTTR_INLINE void create(U&& value, variant_data& dest)
  438. {
  439. COPY_ARRAY_PRE_PROC(value, dest);
  440. }
  441. };
  442. /////////////////////////////////////////////////////////////////////////////////////////
  443. /*!
  444. * This policy is used for raw array types of arbitrary rank, which fit NOT into \p variant_data.
  445. *
  446. * A copy of the given array value will be allocated on the heap. The pointer to the array is stored in \p variant_data.
  447. */
  448. template<typename T>
  449. struct variant_data_policy_array_big : variant_data_base_policy<T, variant_data_policy_array_big<T>>
  450. {
  451. using array_dest_type = decltype(new T);
  452. static RTTR_INLINE const T& get_value(const variant_data& data)
  453. {
  454. return reinterpret_cast<const T&>(*reinterpret_cast<const array_dest_type&>(data));
  455. }
  456. static RTTR_INLINE void destroy(T& value)
  457. {
  458. delete [] &value;
  459. }
  460. static RTTR_INLINE void clone(const T& value, variant_data& dest)
  461. {
  462. reinterpret_cast<array_dest_type&>(dest) = new T;
  463. COPY_ARRAY_PRE_PROC(value, dest);
  464. }
  465. static RTTR_INLINE void swap(T& value, variant_data& dest)
  466. {
  467. reinterpret_cast<array_dest_type&>(dest) = value;
  468. }
  469. template<typename U>
  470. static RTTR_INLINE void create(U&& value, variant_data& dest)
  471. {
  472. using array_dest_type = decltype(new T);
  473. reinterpret_cast<array_dest_type&>(dest) = new T;
  474. COPY_ARRAY_PRE_PROC(value, dest);
  475. }
  476. };
  477. /////////////////////////////////////////////////////////////////////////////////////////
  478. /*!
  479. * This policy is used for all arithmetic types, which fit into the storage of variant_data.
  480. *
  481. * The data will be raw copied into the variant_data.
  482. */
  483. template<typename T>
  484. struct variant_data_policy_arithmetic : variant_data_base_policy<T, variant_data_policy_arithmetic<T>, default_type_converter<T>>
  485. {
  486. static RTTR_INLINE const T& get_value(const variant_data& data)
  487. {
  488. return reinterpret_cast<const T&>(data);
  489. }
  490. static RTTR_INLINE void destroy(T& value)
  491. {
  492. }
  493. static RTTR_INLINE void clone(const T& value, variant_data& dest)
  494. {
  495. reinterpret_cast<T&>(dest) = value;
  496. }
  497. static RTTR_INLINE void swap(T& value, variant_data& dest)
  498. {
  499. clone(value, dest);
  500. }
  501. template<typename U>
  502. static RTTR_INLINE void create(U&& value, variant_data& dest)
  503. {
  504. reinterpret_cast<T&>(dest) = value;
  505. }
  506. };
  507. /////////////////////////////////////////////////////////////////////////////////////////
  508. /*!
  509. * This policy will manage the type std::string.
  510. *
  511. * This type has build in converter for several other basic types, that why we have a specialization here for it.
  512. */
  513. struct RTTR_API variant_data_policy_string : variant_data_policy_big<std::string, default_type_converter<std::string>>
  514. {
  515. template<typename U>
  516. static RTTR_INLINE void create(U&& value, variant_data& dest)
  517. {
  518. reinterpret_cast<std::string*&>(dest) = new std::string(std::forward<U>(value));
  519. }
  520. template<std::size_t N>
  521. static RTTR_INLINE void create(const char (&value)[N], variant_data& dest)
  522. {
  523. reinterpret_cast<std::string*&>(dest) = new std::string(value, N - 1);
  524. }
  525. };
  526. /////////////////////////////////////////////////////////////////////////////////////////
  527. /*!
  528. * This policy is used when the variant does not contain any data. So in fact an invalid variant.
  529. *
  530. * With this approach we avoid checking for an valid variant. E.g. during destruction.
  531. */
  532. struct RTTR_API variant_data_policy_empty
  533. {
  534. static bool invoke(variant_policy_operation op, const variant_data& src_data, argument_wrapper arg)
  535. {
  536. switch (op)
  537. {
  538. case variant_policy_operation::DESTROY:
  539. case variant_policy_operation::CLONE:
  540. case variant_policy_operation::SWAP:
  541. case variant_policy_operation::EXTRACT_WRAPPED_VALUE:
  542. case variant_policy_operation::CREATE_WRAPPED_VALUE:
  543. {
  544. break;
  545. }
  546. case variant_policy_operation::GET_VALUE:
  547. {
  548. arg.get_value<const void*>() = nullptr;
  549. break;
  550. }
  551. case variant_policy_operation::GET_TYPE:
  552. {
  553. arg.get_value<type>() = get_invalid_type();
  554. break;
  555. }
  556. case variant_policy_operation::GET_PTR:
  557. {
  558. arg.get_value<void*>() = nullptr;
  559. break;
  560. }
  561. case variant_policy_operation::GET_RAW_TYPE:
  562. {
  563. arg.get_value<type>() = get_invalid_type();
  564. break;
  565. }
  566. case variant_policy_operation::GET_RAW_PTR:
  567. {
  568. arg.get_value<void*>() = nullptr;
  569. break;
  570. }
  571. case variant_policy_operation::GET_ADDRESS_CONTAINER:
  572. {
  573. data_address_container& data = arg.get_value<data_address_container>();
  574. data.m_type = get_invalid_type();
  575. data.m_wrapped_type = get_invalid_type();
  576. data.m_data_address = nullptr;
  577. data.m_data_address_wrapped_type = nullptr;
  578. break;
  579. }
  580. case variant_policy_operation::IS_ASSOCIATIVE_CONTAINER:
  581. {
  582. return false;
  583. }
  584. case variant_policy_operation::IS_SEQUENTIAL_CONTAINER:
  585. {
  586. return false;
  587. }
  588. case variant_policy_operation::CREATE_ASSOCIATIV_VIEW:
  589. {
  590. break;
  591. }
  592. case variant_policy_operation::CREATE_SEQUENTIAL_VIEW:
  593. {
  594. break;
  595. }
  596. case variant_policy_operation::IS_VALID:
  597. {
  598. return false;
  599. }
  600. case variant_policy_operation::IS_NULLPTR:
  601. {
  602. return false;
  603. }
  604. case variant_policy_operation::CONVERT:
  605. {
  606. return false;
  607. }
  608. case variant_policy_operation::COMPARE_EQUAL:
  609. {
  610. const auto& param = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
  611. const variant& rhs = std::get<1>(param);
  612. bool& ok = std::get<2>(param);
  613. if (!rhs.is_valid())
  614. ok = true;
  615. return ok;
  616. }
  617. case variant_policy_operation::COMPARE_LESS:
  618. {
  619. return false;
  620. }
  621. }
  622. return true;
  623. }
  624. template<typename U>
  625. static RTTR_INLINE void create(U&&, variant_data&)
  626. {
  627. }
  628. };
  629. /////////////////////////////////////////////////////////////////////////////////////////
  630. /*!
  631. * This policy is used when the variant does contain a `void`.
  632. *
  633. * A `void` variant is a special variant to indicate that a function call was successful.
  634. * So in fact it does not contain any data, but the returned type of \ref variant::get_type() is a `void`.
  635. */
  636. struct RTTR_API variant_data_policy_void
  637. {
  638. static bool invoke(variant_policy_operation op, const variant_data& src_data, argument_wrapper arg)
  639. {
  640. switch (op)
  641. {
  642. case variant_policy_operation::DESTROY:
  643. case variant_policy_operation::CLONE:
  644. case variant_policy_operation::SWAP:
  645. case variant_policy_operation::EXTRACT_WRAPPED_VALUE:
  646. {
  647. break;
  648. }
  649. case variant_policy_operation::GET_VALUE:
  650. {
  651. arg.get_value<const void*>() = nullptr;
  652. break;
  653. }
  654. case variant_policy_operation::GET_TYPE:
  655. {
  656. arg.get_value<type>() = type::get<void>();
  657. break;
  658. }
  659. case variant_policy_operation::GET_PTR:
  660. {
  661. arg.get_value<void*>() = nullptr;
  662. }
  663. case variant_policy_operation::GET_RAW_TYPE:
  664. {
  665. arg.get_value<type>() = type::get<void>();
  666. break;
  667. }
  668. case variant_policy_operation::GET_RAW_PTR:
  669. {
  670. arg.get_value<void*>() = nullptr;
  671. break;
  672. }
  673. case variant_policy_operation::GET_ADDRESS_CONTAINER:
  674. {
  675. data_address_container& data = arg.get_value<data_address_container>();
  676. data.m_type = type::get<void>();
  677. data.m_wrapped_type = type::get<void>();
  678. data.m_data_address = nullptr;
  679. data.m_data_address_wrapped_type = nullptr;
  680. break;
  681. }
  682. case variant_policy_operation::IS_ASSOCIATIVE_CONTAINER:
  683. {
  684. return false;
  685. }
  686. case variant_policy_operation::IS_SEQUENTIAL_CONTAINER:
  687. {
  688. return false;
  689. }
  690. case variant_policy_operation::CREATE_ASSOCIATIV_VIEW:
  691. {
  692. break;
  693. }
  694. case variant_policy_operation::CREATE_SEQUENTIAL_VIEW:
  695. {
  696. break;
  697. }
  698. case variant_policy_operation::CREATE_WRAPPED_VALUE:
  699. {
  700. return false;
  701. }
  702. case variant_policy_operation::IS_NULLPTR:
  703. {
  704. return false;
  705. }
  706. case variant_policy_operation::IS_VALID:
  707. {
  708. return true;
  709. }
  710. case variant_policy_operation::CONVERT:
  711. {
  712. return false;
  713. }
  714. case variant_policy_operation::COMPARE_EQUAL:
  715. {
  716. const auto& param = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
  717. const variant& rhs = std::get<1>(param);
  718. bool& ok = std::get<2>(param);
  719. if (rhs.is_type<void>())
  720. ok = true;
  721. return ok;
  722. }
  723. case variant_policy_operation::COMPARE_LESS:
  724. {
  725. return false;
  726. }
  727. }
  728. return true;
  729. }
  730. template<typename U>
  731. static RTTR_INLINE void create(U&&, variant_data&)
  732. {
  733. }
  734. };
  735. /////////////////////////////////////////////////////////////////////////////////////////
  736. /*!
  737. * This policy is used when the variant does contain a `nullptr`.
  738. *
  739. * We need this special handling because MSVC 2013 cannot handle correct a const std::nullptr_t,
  740. * On the other hand we have some special handling for comparison.
  741. */
  742. struct RTTR_API variant_data_policy_nullptr_t
  743. {
  744. static RTTR_INLINE std::nullptr_t& get_value(const variant_data& data)
  745. {
  746. return reinterpret_cast<std::nullptr_t&>(const_cast<variant_data&>(data));
  747. }
  748. static RTTR_INLINE void destroy(std::nullptr_t& value)
  749. {
  750. // for unknown reason we have to fully qualify the dtor call here;
  751. // otherwise mingw has reports a problems here: "request for member 'nullptr_t' in non-class type 'std::nullptr_t'"
  752. value.std::nullptr_t::~nullptr_t();
  753. }
  754. static RTTR_INLINE void clone(const std::nullptr_t& value, variant_data& dest)
  755. {
  756. new (&dest) std::nullptr_t(value);
  757. }
  758. static RTTR_INLINE void swap(std::nullptr_t& value, variant_data& dest)
  759. {
  760. new (&dest) std::nullptr_t(value);
  761. destroy(value);
  762. }
  763. static bool invoke(variant_policy_operation op, const variant_data& src_data, argument_wrapper arg)
  764. {
  765. switch (op)
  766. {
  767. case variant_policy_operation::DESTROY:
  768. {
  769. destroy(get_value(src_data));
  770. break;
  771. }
  772. case variant_policy_operation::CLONE:
  773. {
  774. clone(get_value(src_data), arg.get_value<variant_data>());
  775. break;
  776. }
  777. case variant_policy_operation::SWAP:
  778. {
  779. swap(get_value(src_data), arg.get_value<variant_data>());
  780. break;
  781. }
  782. case variant_policy_operation::CREATE_WRAPPED_VALUE:
  783. {
  784. return false;
  785. }
  786. case variant_policy_operation::EXTRACT_WRAPPED_VALUE:
  787. {
  788. break;
  789. }
  790. case variant_policy_operation::GET_VALUE:
  791. {
  792. arg.get_value<const void*>() = &get_value(src_data);
  793. break;
  794. }
  795. case variant_policy_operation::GET_TYPE:
  796. {
  797. arg.get_value<type>() = type::get<std::nullptr_t>();
  798. break;
  799. }
  800. case variant_policy_operation::GET_PTR:
  801. {
  802. arg.get_value<void*>() = as_void_ptr(std::addressof(get_value(src_data)));
  803. }
  804. case variant_policy_operation::GET_RAW_TYPE:
  805. {
  806. arg.get_value<type>() = type::get<std::nullptr_t>();
  807. break;
  808. }
  809. case variant_policy_operation::GET_RAW_PTR:
  810. {
  811. arg.get_value<void*>() = as_void_ptr(raw_addressof(get_value(src_data)));
  812. break;
  813. }
  814. case variant_policy_operation::GET_ADDRESS_CONTAINER:
  815. {
  816. data_address_container& data = arg.get_value<data_address_container>();
  817. data.m_type = type::get<std::nullptr_t>();
  818. data.m_wrapped_type = type::get<std::nullptr_t>();
  819. data.m_data_address = as_void_ptr(raw_addressof(get_value(src_data)));
  820. data.m_data_address_wrapped_type = as_void_ptr(wrapped_raw_addressof(get_value(src_data)));
  821. break;
  822. }
  823. case variant_policy_operation::IS_ASSOCIATIVE_CONTAINER:
  824. {
  825. return false;
  826. }
  827. case variant_policy_operation::IS_SEQUENTIAL_CONTAINER:
  828. {
  829. return false;
  830. }
  831. case variant_policy_operation::CREATE_ASSOCIATIV_VIEW:
  832. {
  833. break;
  834. }
  835. case variant_policy_operation::CREATE_SEQUENTIAL_VIEW:
  836. {
  837. break;
  838. }
  839. case variant_policy_operation::IS_VALID:
  840. {
  841. return true;
  842. }
  843. case variant_policy_operation::IS_NULLPTR:
  844. {
  845. return true;
  846. }
  847. case variant_policy_operation::CONVERT:
  848. {
  849. return false;
  850. }
  851. case variant_policy_operation::COMPARE_EQUAL:
  852. {
  853. const auto& param = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
  854. const variant& rhs = std::get<1>(param);
  855. bool& ok = std::get<2>(param);
  856. ok = true;
  857. return rhs.is_nullptr();
  858. }
  859. case variant_policy_operation::COMPARE_LESS:
  860. {
  861. const auto& param = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
  862. const variant& lhs = std::get<0>(param);
  863. const variant& rhs = std::get<1>(param);
  864. bool& ok = std::get<2>(param);
  865. ok = true;
  866. return (lhs.is_nullptr() && !rhs.is_nullptr());
  867. }
  868. }
  869. return true;
  870. }
  871. template<typename U>
  872. static RTTR_INLINE void create(U&& value, variant_data& dest)
  873. {
  874. new (&dest) std::nullptr_t(std::forward<U>(value));
  875. }
  876. };
  877. /////////////////////////////////////////////////////////////////////////////////////////
  878. // default export, to reduce compile time, and code bloat
  879. template struct RTTR_API variant_data_policy_arithmetic<bool>;
  880. template struct RTTR_API variant_data_policy_arithmetic<char>;
  881. template struct RTTR_API variant_data_policy_arithmetic<float>;
  882. template struct RTTR_API variant_data_policy_arithmetic<double>;
  883. template struct RTTR_API variant_data_policy_arithmetic<std::uint8_t>;
  884. template struct RTTR_API variant_data_policy_arithmetic<std::uint16_t>;
  885. template struct RTTR_API variant_data_policy_arithmetic<std::uint32_t>;
  886. template struct RTTR_API variant_data_policy_arithmetic<std::uint64_t>;
  887. template struct RTTR_API variant_data_policy_arithmetic<std::int8_t>;
  888. template struct RTTR_API variant_data_policy_arithmetic<std::int16_t>;
  889. template struct RTTR_API variant_data_policy_arithmetic<std::int32_t>;
  890. template struct RTTR_API variant_data_policy_arithmetic<std::int64_t>;
  891. template struct RTTR_API variant_data_policy_small<bool*>;
  892. template struct RTTR_API variant_data_policy_small<char*>;
  893. template struct RTTR_API variant_data_policy_small<float*>;
  894. template struct RTTR_API variant_data_policy_small<double*>;
  895. template struct RTTR_API variant_data_policy_small<std::uint8_t*>;
  896. template struct RTTR_API variant_data_policy_small<std::uint16_t*>;
  897. template struct RTTR_API variant_data_policy_small<std::uint32_t*>;
  898. template struct RTTR_API variant_data_policy_small<std::uint64_t*>;
  899. template struct RTTR_API variant_data_policy_small<std::int8_t*>;
  900. template struct RTTR_API variant_data_policy_small<std::int16_t*>;
  901. template struct RTTR_API variant_data_policy_small<std::int32_t*>;
  902. template struct RTTR_API variant_data_policy_small<std::int64_t*>;
  903. /////////////////////////////////////////////////////////////////////////////////////////
  904. } // end namespace detail
  905. } // end namespace rttr
  906. #endif // RTTR_VARIANT_DATA_POLICY_H_