Так как typeid(T).name()
не возвращает понятное человеку имя типа, это не очень помогает нам, если мы хотим напечатать имя аргументов шаблона для некоторого шаблона класса, особенно когда мы отлаживаем. Мы часто чувствуем, как писать это при отладке:
print<Args...>(cout); //dump the names of all types to stdout!
Итак, я пишу довольно-печатную утилиту, которая дает мне имя шаблона класса. Ну, проще понять это с помощью некоторых примеров использования:
print<int>(cout); //prints int
print<int, double, char>(cout); //prints int, double, char
print<std::string>(cout); //prints std::basic_string<char, .. etc>
print<std::wstring>(cout); //prints std::basic_string<wchar_t, .. etc>
print<X<int,Y<int>>>(cout); //prints X<int, Y<int>>
Внутри я использую шаблон класса template_name
, который возвращает мне "Y"
, когда я передаю Y<int>
ему как аргумент шаблона. Вот как он частично специализирован для каждого шаблона пользовательского класса.
#define DEFINE_TEMPLATE_NAME(template_type) \
template<typename ... Ts>\
struct template_name<template_type<Ts...>>\
{\
static const char* name()\
{\
return #template_type;\
}\
};
И пользователь должен использовать этот макрос для регистрации своего класса шаблонов следующим образом:
DEFINE_TEMPLATE_NAME(std::basic_string);
DEFINE_TEMPLATE_NAME(std::vector);
DEFINE_TEMPLATE_NAME(X); //X is a class template
DEFINE_TEMPLATE_NAME(Y); //Y is a class template
Это работает, потому что специализация template_name<template_type<Ts...>>
является шаблоном вариационного класса только для типов, что означает, что он вернет мне имя шаблона класса , если все параметры шаблона являются типами. Он также способен печатать типы функций и типы-члены-члены:
typedef void fun(int,int);
//lets use snl::name() which returns name instead of printing!
std::cout << snl::name<fun>(); //prints : void(int,int)
std::cout << snl::name<fun*>(); //prints : void(*)(int,int)
См. рабочий код здесь с другими подробными сведениями. Это пока замечательно работает.
Но теперь я улучшаю это и хочу добавить поддержку аргументов tempate не-типов и смешанных аргументов шаблона:
template<int...>
struct Z{};
//non-type template arguments : 1,2,3
snd::print<Z<1,2,3>>(cout); //should print Z<1,2,3>
//mixed template arguments : int, 100
snd::print<std::array<int,100>>(cout); //should print std::array<int,100>
Как мне это сделать? Как получить имя такого шаблона класса и его аргументов в общем?