Вывести имя класса шаблона во время компиляции - PullRequest
0 голосов
/ 24 августа 2018

Я хотел бы знать, возможно ли узнать и вывести имя класса шаблона во время компиляции.Это будет выглядеть примерно так:

template<typename T>
class SomeTemplateClass
{
    SOME_WAY_TO_PRINT_CLASS_NAME(T)
};

Затем каждый раз, когда вызывается класс шаблона, например:

using C = SomeTemplateClass<std::string>;

или

SomeTemplateClass<std::string> instance;

компилятор будет выводить сообщение вроде:

note: Template argument of SomeTemplateClass is std::__cxx11::basic_string<char>

Насколько я искал, я нашел один способ, который приводит к аварийному завершению работы компилятора, давая тип класса:

template<typename T>
class SomeTemplateClass
{
    public:
    using print = typename T::expected_crash;
};

using C = SomeTemplateClass<std::string>;

int main()
{
    C::print err;
    return 0;
}

, который дает:

error: no type named ‘expected_crash’ in ‘class std::__cxx11::basic_string<char>’

Но это скорее взлом, чем чистое решение, и мне было интересно, есть ли другое решение этой проблемы.

Спасибо!

Ответы [ 3 ]

0 голосов
/ 24 августа 2018

Этот шаблон имеет зависимую static_assert, которая всегда будет неудачной. Компиляторы обычно показывают параметры шаблона, которые привели к сбою такого экземпляра.

template<class T>
struct NameOf {
    static_assert(sizeof(T) != sizeof(T), "");
};

Демо

<source>: In instantiation of 'struct NameOf<SomeClass>':                  // <---
<source>:18:15:   required from 'void foo(const T&) [with T = SomeClass]'  // <---
<source>:24:10:   required from here
<source>:9:29: error: static assertion failed
9 |     static_assert(sizeof(T) != sizeof(T), "");
  |                   ~~~~~~~~~~^~~~~~~~~~~~

Вы можете сделать то же самое, чтобы ваш компилятор сообщал вам значение времени компиляции произвольного целого числа:

template<int I>
struct CompileTimeValueOf {
    static_assert(I != I, "");
};

CompileTimeValueOf<sizeof(double)> x;

Обратите внимание, что это, конечно, приведет к сбою компиляции, так что это просто для временной проверки. Для чего-то менее разрушительного, вам, вероятно, придется прибегнуть к специфичным для компилятора расширениям. См. Например здесь .

0 голосов
/ 27 августа 2018

Существует другой хакерский способ вывода имени класса шаблона при компиляции, но без сбоя компилятора.Можно использовать предупреждение, здесь предупреждение о неиспользованной переменной.

#define PRINT(T) template<typename T> \
int print_##T() \
{ \
    int type_of_##T = 0; \
    return 0; \
};\
int res_##T = print_##T<T>();

С этим (и флагом -Wunused-variable) вы можете написать

PRINT(T)

, чтобы узнать тип T. Более того, это решение можно использовать внутрикласс, создав метод, подобный этому:

template<typename T>
class SomeTemplateClass
{
    public:
        static int print()
        {
            int type_of_T = 0;
            return 0;
        };
};

Метод, который будет вызываться извне:

int useless = SomeTemplateClass<T>::print();

Так что это по-прежнему хак, но по крайней мере компилятор несбой больше.

0 голосов
/ 24 августа 2018

Вы можете использовать typeid(T).name() для определения названия класса.

...