fixedTuple.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _FIXEDTUPLE_H_
  23. #define _FIXEDTUPLE_H_
  24. #include "engineTypes.h"
  25. /// @name Fixed-layout tuple definition
  26. /// These structs and templates serve as a way to pass arguments from external
  27. /// applications and into the T3D console system.
  28. /// They work as std::tuple, but they ensure a standardized fixed memory
  29. /// layout. Allowing for unmanaged calls with these tuples as the parameter
  30. /// lists.
  31. ///
  32. /// The implementation is from a SO solution:
  33. /// https://codereview.stackexchange.com/a/52279
  34. /// As out use-case is pretty simple, this code could probably be simplified by
  35. /// stripping out a lot of extra functionality. But eh.
  36. ///
  37. /// @{
  38. template <typename ...Ts>
  39. struct fixed_tuple;
  40. template <typename T, typename ...Ts>
  41. struct fixed_tuple<T, Ts...>
  42. {
  43. T first;
  44. fixed_tuple<Ts...> rest;
  45. fixed_tuple() = default;
  46. template <class U, class...Us, class = typename ::std::enable_if<!::std::is_base_of<fixed_tuple, typename ::std::decay<U>::type>::value>::type>
  47. fixed_tuple(U&& u, Us&&...tail) :
  48. first(::std::forward<U>(u)),
  49. rest(::std::forward<Us>(tail)...) {}
  50. };
  51. template <typename T>
  52. struct fixed_tuple<T>
  53. {
  54. T first;
  55. fixed_tuple() = default;
  56. template <class U, class = typename ::std::enable_if<!::std::is_base_of<fixed_tuple, typename ::std::decay<U>::type>::value>::type>
  57. fixed_tuple(U&& u) :
  58. first(::std::forward<U>(u)) {}
  59. };
  60. template <>
  61. struct fixed_tuple<> {};
  62. template < ::std::size_t i, class T>
  63. struct fixed_tuple_element;
  64. template < ::std::size_t i, class T, class... Ts>
  65. struct fixed_tuple_element<i, fixed_tuple<T, Ts...> >
  66. : fixed_tuple_element<i - 1, fixed_tuple<Ts...> >
  67. {};
  68. template <class T, class... Ts>
  69. struct fixed_tuple_element<0, fixed_tuple<T, Ts...> >
  70. {
  71. using type = T;
  72. };
  73. template < ::std::size_t i>
  74. struct fixed_tuple_accessor
  75. {
  76. template <class... Ts>
  77. static inline typename fixed_tuple_element<i, fixed_tuple<Ts...> >::type & get(fixed_tuple<Ts...> & t)
  78. {
  79. return fixed_tuple_accessor<i - 1>::get(t.rest);
  80. }
  81. template <class... Ts>
  82. static inline const typename fixed_tuple_element<i, fixed_tuple<Ts...> >::type & get(const fixed_tuple<Ts...> & t)
  83. {
  84. return fixed_tuple_accessor<i - 1>::get(t.rest);
  85. }
  86. };
  87. template <>
  88. struct fixed_tuple_accessor<0>
  89. {
  90. template <class... Ts>
  91. static inline typename fixed_tuple_element<0, fixed_tuple<Ts...> >::type & get(fixed_tuple<Ts...> & t)
  92. {
  93. return t.first;
  94. }
  95. template <class... Ts>
  96. static inline const typename fixed_tuple_element<0, fixed_tuple<Ts...> >::type & get(const fixed_tuple<Ts...> & t)
  97. {
  98. return t.first;
  99. }
  100. };
  101. #pragma warning( push )
  102. #pragma warning( disable : 4267 )
  103. template <size_t I, class... Ts>
  104. static U32 fixed_tuple_offset(fixed_tuple<Ts...>& t)
  105. {
  106. return (U32)((size_t)& fixed_tuple_accessor<I>::get(t)) - ((size_t)& t);
  107. }
  108. template <size_t I, class... Ts>
  109. static U32 fixed_tuple_offset(const fixed_tuple<Ts...>& t)
  110. {
  111. return (U32)((size_t)& fixed_tuple_accessor<I>::get(t)) - ((size_t)& t);
  112. }
  113. #pragma warning(pop)
  114. template< typename T1, typename T2 >
  115. struct fixed_tuple_mutator {};
  116. template<typename... Tdest, typename... Tsrc>
  117. struct fixed_tuple_mutator<void(Tdest...), void(Tsrc...)>
  118. {
  119. template<std::size_t I = 0>
  120. static inline typename std::enable_if<I == sizeof...(Tsrc), void>::type
  121. copy_r_t_l(fixed_tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  122. { }
  123. template<std::size_t I = 0>
  124. static inline typename std::enable_if<I < sizeof...(Tsrc), void>::type
  125. copy_r_t_l(fixed_tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  126. {
  127. fixed_tuple_accessor<I + (sizeof...(Tdest)-sizeof...(Tsrc))>::get(dest) = fixed_tuple_accessor<I>::get(src);
  128. copy_r_t_l<I + 1>(src, dest);
  129. }
  130. template<std::size_t I = 0>
  131. static inline typename std::enable_if<I == sizeof...(Tsrc), void>::type
  132. copy(std::tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  133. { }
  134. template<std::size_t I = 0>
  135. static inline typename std::enable_if<I < sizeof...(Tsrc), void>::type
  136. copy(std::tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  137. {
  138. fixed_tuple_accessor<I>::get(dest) = std::get<I>(src);
  139. copy<I + 1>(src, dest);
  140. }
  141. };
  142. /// @}
  143. #endif // !_FIXEDTUPLE_H_