Печатать имя типа во время компиляции, не прерывая компиляцию?

В этом вопросе:

Печать имени типа шаблона во время компиляции

у нас есть несколько предложений относительно того, как заставить типичные компиляторы C++ печатать имя типа во время компиляции. Однако они полагаются на срабатывание ошибки компиляции.

Мой вопрос: могу ли я заставить компилятор C++ печатать имя типа без остановки компиляции?

В общем, ответ - "вероятно, нет", потому что действительная программа может быть скомпилирована в целевой объект без какой-либо печати, поэтому я конкретно спрашиваю о GCC и clang, с возможным использованием директив препроцессора, встроенных функций компилятора или любого компилятора. -специфический трюк.

Примечания:

  • Очевидно, что проблема заключается в типах печати за using/typedef операторы, значения параметров шаблона, вариативные шаблоны и т. д. Если тип доступен явно, вы можете просто использовать что-то вроде #message "my type is unsigned long long"(как предложил @NutCracker). Но вопрос не в этом.
  • Ответы, основанные на C++11 или более ранней версии, предпочтительнее, чем требовать C++14/17/20.

3 ответа

Решение

Следующий механизм связан с @JonathanWakely и специфичен для GCC:

int i;

template <typename T>
[[gnu::warning("your type here")]]
bool print_type() { return true; }

bool b = print_type<decltype(i)>();

Это дает вам:

<source>:In function 'void __static_initialization_and_destruction_0(int, int)':
<source>:7:33: warning: call to 'print_type<int>' declared with attribute warning: your
type here [-Wattribute-warning]
    7 | bool b = print_type<decltype(i)>();
      |          ~~~~~~~~~~~~~~~~~~~~~~~^~

Посмотрите, как это работает на Godbolt.

В c++17 мы можем злоупотреблять [[deprecated]]атрибут, чтобы заставить компилятор выдать предупреждение, содержащее нужный параметр шаблона:

      template<typename T>
[[deprecated]] inline constexpr void print_type(T&& t, const char* msg=nullptr){}

print_type(999, "I just want to know the type here...");

Фрагмент выше выведет следующее предупреждение с помощью gcc:

      <source>:32:59: warning: 'constexpr void print_type(T&&, const char*) [with T = int]' is deprecated [-Wdeprecated-declarations]
     print_type(999, "I just want to know the type here...");

В отличие от принятого ответа, это будет работать с каждым компилятором, совместимым с С++17. Обратите внимание, что вам нужно будет включить \W3` на MSVC.

Мы можем даже пойти дальше и определить статический макрос assert, который будет печатать тип тогда и только тогда, когда он терпит неудачу.

      template<bool b, typename T>
inline constexpr bool print_type_if_false(T&& t) {
    if constexpr (!b)
        print_type(std::forward<T>(t));
    return b;
}

// Some nice static assert that will print the type if it fails.
#define STATIC_ASSERT(x,condition, msg) static_assert(print_type_if_false<condition>(x), msg);

Вот живой пример.

Gcc и clang предлагают некоторый интерфейс для использования собственных плагинов, которые могут делать почти все на разных этапах от синтаксического анализа до генерации кода.

Интерфейсы зависят от компилятора, и, поскольку этот плагин для gcc не может использоваться для clang или наоборот.

Документация полна, и здесь нет возможности вдаваться в подробности, поэтому я указываю вам только на документы из gcc и clang:

плагин gcc плагин clang

Другие вопросы по тегам