Вот еще один набор кода с удобной функцией return_type
, который вы можете использовать для доступа к любому типу по определенному индексу в произвольном списке шаблонов ... затем вы можете адаптировать вызов к return_type
, чтобы получитьпервый и последний аргументы (т. е. первый аргумент будет в 0, а последний аргумент будет в sizeof...(TypeList)
):
template<typename T>
struct type_id_struct
{
typedef T type;
T object_instance;
};
template<int N, typename... TypeList>
struct reduce {};
template<int N, typename T1, typename... TypeList>
struct reduce<N, T1, TypeList...>
{
typedef typename reduce<N - 1, TypeList... >::type type;
};
template<typename T1, typename... TypeList>
struct reduce<0, T1, TypeList...>
{
typedef T1 type;
};
//convenience function
template<int N, typename... TypeList>
type_id_struct<typename reduce<N, TypeList...>::type> return_type()
{
return type_id_struct<typename reduce<N, TypeList...>::type>();
}
Вот пример использования вспомогательной функции return_type
в фактическомкод для определения N-го аргумента шаблона в шаблоне переменной:
int main()
{
auto type_returned = return_type<2, int, double, char>();
std::cout << typeid(type_returned.object_instance).name() << std::endl;
return 0;
}
В этом случае, поскольку аргумент шаблона int
для return_type
равен 2
, вы получите тип char
в качестве выхода.Любое число, превышающее 2
, вызовет переполнение, что приведет к ошибке компиляции, а не к ошибке времени выполнения.Как уже отмечалось, вы можете адаптировать его так, чтобы он был заключен в функцию в структуре, которая позволит вам получить доступ к типам в шаблоне переменных для этого конкретного экземпляра структуры, используя sizeof...(TypeList) - 1
, примененный к перечислению.Например:
template<typename... TypeList>
struct an_object
{
enum { first = 0, last = (sizeof...(TypeList) - 1) };
template<int N>
auto wrapper() -> decltype(return_type<N, TypeList...>())
{
return return_type<N, TypeList...>();
}
};
//...more code
int main()
{
an_object<int, double, char> a;
auto r_type1 = a.wrapper<an_object<int, double, char>::first>();
std::cout << typeid(r_type1.object_instance).name() << std::endl;
auto r_type2 = a.wrapper<an_object<int, double, char>::last>();
std::cout << typeid(r_type2.object_instance).name() << std::endl;
return 0;
}