Автоматически подсчитывать количество экземпляров классов в TMP?

Учитывая метапрограмму шаблона (TMP), компиляторы С++ производят статистику сборки, которая подсчитывает количество экземпляров классов? Или есть ли другой способ автоматически получить этот номер? Так, например, оберенный факториал

#include <iostream>

template<int N> struct fact { enum { value = N * fact<N-1>::value }; };
template<> struct fact<1> { enum { value = 1 }; };

int main()
{
    const int x = fact<3>::value;
    std::cout << x << "\n";
    return 0;
}

Я хотел бы вернуть номер 3 (поскольку экземпляр факта < 3, fact < 2 & and fact < 1). Этот пример, если, конечно, тривиальный, но всякий раз, когда вы начинаете использовать, например, Boost.MPL, время компиляции действительно взорвалось, и я хотел бы знать, сколько из этого происходит из-за скрытых классов. Мой вопрос в первую очередь для Visual С++, но ответы на gcc также будут оценены.

EDIT: мой текущий очень хрупкий подход для Visual С++ добавляет компилятор с одного из файлов Stephan T. Lavavej /d1reportAllClassLayout и делает счетчик grep + слов в выходном файле, но он (a) увеличивает время компиляции и (b) регулярное выражение не может получить 100% правильно.

Ответ 1

Я сделал однострочное изменение в GCC, что заставляет его распечатывать имя каждого шаблона класса, поскольку оно создает его. Вы уже можете вызывать front-end С++ cc1plus напрямую без флага -quiet, чтобы получить то же самое для шаблонов функций.

У меня нет возможности превратить это в подходящий вариант GCC, это просто взломать в моем исходном дереве. Я собираюсь реализовать его как плагин вместо этого, но он не находится рядом с моим списком TODO.

Ответ 2

Существует, конечно, нет портативного способа сделать это.

Существуют хакерские способы сделать это для большинства компиляторов. Вы уже нашли его для MSVC. Для gcc вы можете использовать gccxml. Или, для любого компилятора с открытым исходным кодом (gcc или clang), должно быть довольно просто добавить код в момент создания экземпляра, который либо держит счет, либо регистрирует что-то, что вы можете фильтровать после завершения компиляции.

Для Clang/LLVM вы можете просто создать плагин, который перехватывает экземпляр, что намного чище, но, вероятно, больше работает.

Строка с отладочными символами, без оптимизации и без зачистки может заканчиваться искаженными именами каждого экземпляра, для которого вы можете grep. Однако некоторые компиляторы (включая gcc) всегда будут включать как минимум некоторые методы, независимо от того, хотите вы их или нет. Если вы хотите изменить свой код, вы, вероятно, можете заставить его создавать внеуровневые экземпляры, возможно, что-то вроде этого:

template<int N> struct fact { 
  enum { value = N * fact<N-1>::value }; 
  int *dummy() { return &fact<N-1>::value; }
};

Ответ 3

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