wrapper_mapper.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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_WRAPPER_MAPPER_H_
  28. #define RTTR_WRAPPER_MAPPER_H_
  29. #include "rttr/detail/base/core_prerequisites.h"
  30. namespace rttr
  31. {
  32. //////////////////////////////////////////////////////////////////////////////////////
  33. namespace detail { struct invalid_wrapper_type { }; }
  34. /*!
  35. * The \ref wrapper_mapper class is a class template to access different wrapper types via one common interface.
  36. *
  37. * A wrapper type is a class which encapsulate an instance of another type.
  38. * This are for instance smart pointer classes, e.g. `std::shared_ptr<T>` or `std::unique_ptr<T>`.
  39. * Out of the box, RTTR recognize following wrapper types:
  40. * - \p `std::shared_ptr<T>`
  41. * - \p `std::reference_wrapper<T>`
  42. * - \p `std::weak_ptr<T>`
  43. * - \p `std::unique_ptr<T>`
  44. *
  45. * Custom wrapper types
  46. * --------------------
  47. * In order to work with custom wrapper types, its required to specialize the class
  48. * \ref rttr::wrapper_mapper<T> "wrapper_mapper<T>". Therefore you have to provide two nested type aliases:
  49. * 1. `using wrapped_type = typename T::encapsulated_type;`
  50. * 2. `using type = T`
  51. *
  52. * And three functions:
  53. * 1. `static wrapped_type get(const T& obj);`
  54. * 2. `static T create(wrapped_type& obj);` (Optional)
  55. * 3. `static T<U> convert(const type& source, bool& ok);` (Optional)
  56. *
  57. * \remark The \ref rttr::wrapper_mapper<T>::create(T& obj) "create()" function is optional. When no one is provided,
  58. * then it will be not possible to convert from the wrapped type to the wrapper class from inside a variant.
  59. * The \ref rttr::wrapper_mapper<T>::convert(const type& source, bool& ok) "convert()" function is also optional.
  60. * When no one is provided, you cannot use the \ref rttr::type::register_wrapper_converter_for_base_classes<T>()
  61. * function. For the wrapper classes: `std::shared_ptr<T>` and `std::reference_wrapper<T>`
  62. * default conversion functions are included.
  63. *
  64. * \see variant::convert()
  65. *
  66. * Following code example illustrates how to add a specialization:
  67. * \code{.cpp}
  68. *
  69. * // custom_type.h
  70. *
  71. * template<typename T>
  72. * class custom_type
  73. * {
  74. * public:
  75. * custom_type(T& obj) : m_data(std::addressof(obj)) {}
  76. * custom_type(T) : m_data(nullptr) {}
  77. * T& get_data() { return *m_value; }
  78. * private:
  79. * T* m_data;
  80. * };
  81. *
  82. * // the best place for the specialization, is in the same header file like the type itself
  83. * namespace rttr
  84. * {
  85. *
  86. * template<typename T>
  87. * struct wrapper_mapper<custom_type<T>>
  88. * {
  89. * using wrapped_type = decltype(std::declval<custom_type<T>>().get_data());
  90. * using type = custom_type<T>;
  91. *
  92. * inline static wrapped_type get(const type& obj)
  93. * {
  94. * return obj.get_data();
  95. * }
  96. *
  97. * inline static type create(const wrapped_type& value)
  98. * {
  99. * return custom_type<T>(value);
  100. * }
  101. *
  102. * template<typename U>
  103. * inline static custom_type<U> convert(const type& source, bool& ok)
  104. * {
  105. * if (auto obj = rttr_cast<typename custom_type<U>::wrapped_type*>(&source.get_data()))
  106. * {
  107. * ok = true;
  108. * return custom_type<U>(*obj);
  109. * }
  110. * else
  111. * {
  112. * ok = false;
  113. * return custom_type<U>();
  114. * }
  115. * }
  116. * };
  117. *
  118. * } // end namespace rttr
  119. * \endcode
  120. *
  121. * \remark
  122. * It is very important that the type alias for `wrapped_type` is the actual return type of the getter function.
  123. * Make also sure you put your specialization inside the namespace `rttr`.
  124. * The best place for this code, is below the declaration of your wrapper type.
  125. * When this is not possible, include your specialization code before registering your types to RTTR.
  126. */
  127. template<typename T>
  128. struct wrapper_mapper
  129. {
  130. #ifndef DOXYGEN
  131. using wrapped_type = detail::invalid_wrapper_type;
  132. using type = T;
  133. #else
  134. using wrapped_type = typename wrapper_type::encapsulated_type;
  135. using type = T;
  136. inline static wrapped_type get(const type& obj)
  137. {
  138. return obj.get();
  139. }
  140. inline static type create(const wrapped_type& value)
  141. {
  142. return type(value);
  143. }
  144. template<typename U>
  145. inline static T<U> convert(const type& source, bool& ok)
  146. {
  147. return type(value);
  148. }
  149. #endif
  150. };
  151. //////////////////////////////////////////////////////////////////////////////////////
  152. } // end namespace rttr
  153. #include "rttr/detail/impl/wrapper_mapper_impl.h"
  154. #endif // RTTR_WRAPPER_MAPPER_H_