Подтвердить что ты не робот

Довольно печатные типы и шаблон шаблона вместе со всеми его аргументами шаблона

Так как 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>

Как мне это сделать? Как получить имя такого шаблона класса и его аргументов в общем?

4b9b3361

Ответ 1

Мне жаль, что это "отрицательный ответ" (я поднимаю ваш вопрос), но я боюсь, что вы не сможете этого сделать. Даже рассматривая только шаблонные классы, которые принимают однородные списки непиковых параметров (например, template<int, int>, template<char, char, char> и т.д.), Вам понадобится специализация такого рода:

template<typename T>
struct single_type
{
    // ...
};

template<typename U, template<U...> class C, U... Us>
struct single_type<C<Us...>>
{
    // ...
};

Эта специализация является законной, но бесполезной, потому что тип аргумента U никогда не может быть выведен. Вы можете определить специализированные специализации для единообразных списков литералов наиболее распространенных типов (int..., char... и т.д.), Но было бы невозможно охватить последовательности гетерогенных типов, не говоря уже о последовательностях смешанных аргументов.

Я боюсь, нам придется подождать, пока С++ поддержит отражение, чтобы добиться того, что вы ищете.