//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #ifndef _FIXEDTUPLE_H_ #define _FIXEDTUPLE_H_ #include "engineTypes.h" /// @name Fixed-layout tuple definition /// These structs and templates serve as a way to pass arguments from external /// applications and into the T3D console system. /// They work as std::tuple, but they ensure a standardized fixed memory /// layout. Allowing for unmanaged calls with these tuples as the parameter /// lists. /// /// The implementation is from a SO solution: /// https://codereview.stackexchange.com/a/52279 /// As out use-case is pretty simple, this code could probably be simplified by /// stripping out a lot of extra functionality. But eh. /// /// @{ template struct fixed_tuple; template struct fixed_tuple { T first; fixed_tuple rest; fixed_tuple() = default; template ::type>::value>::type> fixed_tuple(U&& u, Us&&...tail) : first(::std::forward(u)), rest(::std::forward(tail)...) {} }; template struct fixed_tuple { T first; fixed_tuple() = default; template ::type>::value>::type> fixed_tuple(U&& u) : first(::std::forward(u)) {} }; template <> struct fixed_tuple<> {}; template < ::std::size_t i, class T> struct fixed_tuple_element; template < ::std::size_t i, class T, class... Ts> struct fixed_tuple_element > : fixed_tuple_element > {}; template struct fixed_tuple_element<0, fixed_tuple > { using type = T; }; template < ::std::size_t i> struct fixed_tuple_accessor { template static inline typename fixed_tuple_element >::type & get(fixed_tuple & t) { return fixed_tuple_accessor::get(t.rest); } template static inline const typename fixed_tuple_element >::type & get(const fixed_tuple & t) { return fixed_tuple_accessor::get(t.rest); } }; template <> struct fixed_tuple_accessor<0> { template static inline typename fixed_tuple_element<0, fixed_tuple >::type & get(fixed_tuple & t) { return t.first; } template static inline const typename fixed_tuple_element<0, fixed_tuple >::type & get(const fixed_tuple & t) { return t.first; } }; #pragma warning( push ) #pragma warning( disable : 4267 ) template static U32 fixed_tuple_offset(fixed_tuple& t) { return (U32)((size_t)& fixed_tuple_accessor::get(t)) - ((size_t)& t); } template static U32 fixed_tuple_offset(const fixed_tuple& t) { return (U32)((size_t)& fixed_tuple_accessor::get(t)) - ((size_t)& t); } #pragma warning(pop) template< typename T1, typename T2 > struct fixed_tuple_mutator {}; template struct fixed_tuple_mutator { template static inline typename std::enable_if::type copy_r_t_l(fixed_tuple& src, fixed_tuple& dest) { } template static inline typename std::enable_if::type copy_r_t_l(fixed_tuple& src, fixed_tuple& dest) { fixed_tuple_accessor::get(dest) = fixed_tuple_accessor::get(src); copy_r_t_l(src, dest); } template static inline typename std::enable_if::type copy(std::tuple& src, fixed_tuple& dest) { } template static inline typename std::enable_if::type copy(std::tuple& src, fixed_tuple& dest) { fixed_tuple_accessor::get(dest) = std::get(src); copy(src, dest); } }; /// @} #endif // !_FIXEDTUPLE_H_