fixedTuple.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. /// @name Fixed-layout tuple definition
  25. /// These structs and templates serve as a way to pass arguments from external
  26. /// applications and into the T3D console system.
  27. /// They work as std::tuple, but they ensure a standardized fixed memory
  28. /// layout. Allowing for unmanaged calls with these tuples as the parameter
  29. /// lists.
  30. ///
  31. /// The implementation is from a SO solution:
  32. /// https://codereview.stackexchange.com/a/52279
  33. /// As out use-case is pretty simple, this code could probably be simplified by
  34. /// stripping out a lot of extra functionality. But eh.
  35. ///
  36. /// @{
  37. template <typename ...Ts>
  38. struct fixed_tuple;
  39. template <typename T, typename ...Ts>
  40. struct fixed_tuple<T, Ts...>
  41. {
  42. T first;
  43. fixed_tuple<Ts...> rest;
  44. fixed_tuple() = default;
  45. template <class U, class...Us, class = typename ::std::enable_if<!::std::is_base_of<fixed_tuple, typename ::std::decay<U>::type>::value>::type>
  46. fixed_tuple(U&& u, Us&&...tail) :
  47. first(::std::forward<U>(u)),
  48. rest(::std::forward<Us>(tail)...) {}
  49. };
  50. template <typename T>
  51. struct fixed_tuple<T>
  52. {
  53. T first;
  54. fixed_tuple() = default;
  55. template <class U, class = typename ::std::enable_if<!::std::is_base_of<fixed_tuple, typename ::std::decay<U>::type>::value>::type>
  56. fixed_tuple(U&& u) :
  57. first(::std::forward<U>(u)) {}
  58. };
  59. template <>
  60. struct fixed_tuple<> {};
  61. template < ::std::size_t i, class T>
  62. struct fixed_tuple_element;
  63. template < ::std::size_t i, class T, class... Ts>
  64. struct fixed_tuple_element<i, fixed_tuple<T, Ts...> >
  65. : fixed_tuple_element<i - 1, fixed_tuple<Ts...> >
  66. {};
  67. template <class T, class... Ts>
  68. struct fixed_tuple_element<0, fixed_tuple<T, Ts...> >
  69. {
  70. using type = T;
  71. };
  72. template < ::std::size_t i>
  73. struct fixed_tuple_accessor
  74. {
  75. template <class... Ts>
  76. static inline typename fixed_tuple_element<i, fixed_tuple<Ts...> >::type & get(fixed_tuple<Ts...> & t)
  77. {
  78. return fixed_tuple_accessor<i - 1>::get(t.rest);
  79. }
  80. template <class... Ts>
  81. static inline const typename fixed_tuple_element<i, fixed_tuple<Ts...> >::type & get(const fixed_tuple<Ts...> & t)
  82. {
  83. return fixed_tuple_accessor<i - 1>::get(t.rest);
  84. }
  85. };
  86. template <>
  87. struct fixed_tuple_accessor<0>
  88. {
  89. template <class... Ts>
  90. static inline typename fixed_tuple_element<0, fixed_tuple<Ts...> >::type & get(fixed_tuple<Ts...> & t)
  91. {
  92. return t.first;
  93. }
  94. template <class... Ts>
  95. static inline const typename fixed_tuple_element<0, fixed_tuple<Ts...> >::type & get(const fixed_tuple<Ts...> & t)
  96. {
  97. return t.first;
  98. }
  99. };
  100. template< typename T1, typename T2 >
  101. struct fixed_tuple_mutator {};
  102. template<typename... Tdest, typename... Tsrc>
  103. struct fixed_tuple_mutator<void(Tdest...), void(Tsrc...)>
  104. {
  105. template<std::size_t I = 0>
  106. static inline typename std::enable_if<I == sizeof...(Tsrc), void>::type
  107. copy_r_t_l(fixed_tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  108. { }
  109. template<std::size_t I = 0>
  110. static inline typename std::enable_if<I < sizeof...(Tsrc), void>::type
  111. copy_r_t_l(fixed_tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  112. {
  113. fixed_tuple_accessor<I + (sizeof...(Tdest)-sizeof...(Tsrc))>::get(dest) = fixed_tuple_accessor<I>::get(src);
  114. copy_r_t_l<I + 1>(src, dest);
  115. }
  116. template<std::size_t I = 0>
  117. static inline typename std::enable_if<I == sizeof...(Tsrc), void>::type
  118. copy(std::tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  119. { }
  120. template<std::size_t I = 0>
  121. static inline typename std::enable_if<I < sizeof...(Tsrc), void>::type
  122. copy(std::tuple<Tsrc...>& src, fixed_tuple<Tdest...>& dest)
  123. {
  124. fixed_tuple_accessor<I>::get(dest) = std::get<I>(src);
  125. copy<I + 1>(src, dest);
  126. }
  127. };
  128. /// @}
  129. #endif // !_FIXEDTUPLE_H_