///////////////////////////////////////////////////////////////////////////// // Copyright (c) Electronic Arts Inc. All rights reserved. ///////////////////////////////////////////////////////////////////////////// #ifndef EASTL_META_H #define EASTL_META_H #include #include #if defined(EA_PRAGMA_ONCE_SUPPORTED) #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. #endif //////////////////////////////////////////////////////////////////////////////////////////// // This file contains meta programming utilities that are internal to EASTL. We reserve // the right to change this file at any time as it is only intended to be used internally. //////////////////////////////////////////////////////////////////////////////////////////// namespace eastl { namespace meta { //////////////////////////////////////////////////////////////////////////////////////////// // get_type_index_v // // Linearly searches a typelist using compile-time recursion to inspect each T in // the typelist and returns its index, if the type is found. If the T isn't found // in the typelist -1 is returned. // namespace Internal { template struct get_type_index; template struct get_type_index { static const int value = is_same_v ? I : get_type_index::value; }; template struct get_type_index { static const int value = -1; }; } template struct get_type_index { static const int value = Internal::get_type_index<0, T, Types...>::value; }; template constexpr int get_type_index_v = get_type_index::value; //////////////////////////////////////////////////////////////////////////////////////////// // get_type_at // // This traverses the variadic type list and retrieves the type at the user provided index. // template struct get_type_at_helper; template struct get_type_at_helper { typedef typename get_type_at_helper::type type; }; template struct get_type_at_helper<0, Head, Tail...> { typedef Head type; }; template using get_type_at_t = typename get_type_at_helper::type; //////////////////////////////////////////////////////////////////////////////////////////// // type_count_v // // Returns the number of occurrences of type T in a typelist. // template struct type_count; template struct type_count { static const int value = (is_same_v ? 1 : 0) + type_count::value; }; template struct type_count { static const int value = 0; }; template constexpr int type_count_v = type_count::value; //////////////////////////////////////////////////////////////////////////////////////////// // duplicate_type_check_v // // Checks if a type T occurs in a typelist more than once. // template struct duplicate_type_check { static const bool value = (type_count::value == 1); }; template constexpr bool duplicate_type_check_v = duplicate_type_check::value; ////////////////////////////////////////////////////////////////////////////////// // type_list // // type_list is a simple struct that allows us to pass template parameter packs // around in a single struct, and deduce parameter packs from function arguments // like so: // // template void foo(type_list); // foo(type_list); // deduces Ts... as A, B, C // template struct type_list {}; ////////////////////////////////////////////////////////////////////////////////// // unique_type_list // // unique_type_list is a meta-function which takes a parameter pack as its // argument, and returns a type_list with duplicate types removed, like so: // // unique_type_list::type; // type = type_list // unique_type_list::type; // type = type_list // // To use unique_type_list, specialize a variadic class template for a single // type parameter, which is type_list: // // template struct foo {}; // template struct foo> {}; // // Then instantiate the template with unique_type_list_t as its parameter: // // template struct bar : public foo> {} // // See overload_set below for examples. template struct unique_type_list : public unique_type_list { template static enable_if_t...>, type_list> types(type_list); template static enable_if_t...>, type_list> types(type_list); typedef decltype(types(declval::type>())) type; }; template struct unique_type_list { using type = type_list; }; template using unique_type_list_t = typename unique_type_list::type; //////////////////////////////////////////////////////////////////////////////////////////// // overload_resolution_t // // Given an input type and a typelist (which is a stand-in for alternative // function overloads) this traits will return the same type chosen as if // overload_resolution has selected a function to run. // // a single overload of an individual type template struct overload { // Overload is implicitly convertible to the surrogated function // call for pointer to member functions (pmf). This gets around // variadic pack expansion in a class using statement being a C++17 // language feature. It is the core mechanism of aggregating all the // individual overloads into the overload_set structure. using F = T (*)(T); operator F() const { return nullptr; } }; template struct overload_set_impl; template struct overload_set_impl> : public overload... {}; template struct overload_set : public overload_set_impl> { // encapsulates the overloads matching the types of the variadic pack }; EA_DISABLE_VC_WARNING(4242 4244) // conversion from 'T' to 'U', possible loss of data. template ()(declval()))> struct overload_resolution { // capture the return type of the function the compiler selected by // performing overload resolution on the overload set parameter using type = ResultT; }; EA_RESTORE_VC_WARNING() template using overload_resolution_t = typename overload_resolution, OverloadSet>::type; } // namespace meta } // namespace eastl #endif // EASTL_META_H