Это действительно не ответ на ваш вопрос. Это скорее побочное наблюдение.
Я тоже не адвокат по языку C ++, и поэтому могу быть немного не в себе с некоторыми деталями.
Но грубая идея должна быть правильной.
Основная причина, по которой компиляторам C ++ требуется так много времени для компиляции шаблонных метапрограмм, заключается в способе определения шаблонных метапрограмм.
Они не указаны напрямую как код, который вы хотите, чтобы компилятор запускал во время компиляции. Возьмите пример вычисления длины списка типов.
Если бы вы могли написать код, подобный этому:
compile_time size_t GetLength(TypeList * pTypeList)
{
return DoGetLength(pTypeList, 0);
}
compile_time size_t DoGetLength(TypeList * pTypeList, size_t currentLength)
{
if (pTypeList)
{
return DoGetLength(pTypeList->Next, ++currentLength);
}
else
{
return currentLength;
}
}
Это было бы как-то компилировано отдельно от кода, в котором он использовался, и было открыто для языка через некоторый синтаксис, тогда компилятор мог бы выполнить его очень быстро.
Это был бы простой рекурсивный вызов функции.
Можно разработать язык, который допускает подобные вещи. Большинство из них, которые делают это (например, lisp), имеют динамическую типизацию, но это возможно при статической типизации. Однако вряд ли это когда-нибудь будет реализовано в C ++.
Однако проблема в C ++ состоит в том, что код написан так:
template <typename First, typename Second>
struct TypeList
{
typedef First Head;
typedef Second Tail;
};
template <>
struct ListSize<NullType>
{
enum { size = 0 };
};
template <typename Head, typename Tail>
struct ListSize<TypeList<Head, Tail> >
{
enum { size = 1 + ListSize<Tail>::size };
};
Чтобы компилятор "выполнил" метапрограмму, он должен:
- Построить граф зависимостей для начальных значений значения перечисления "size"
- Построить тип шаблона для каждого ребра на графике
- Свяжите все символы, на которые ссылается каждый тип созданного шаблона
- Топологически отсортировать граф зависимостей
- Пройдите по графику и оцените константы
Это намного дороже, чем просто запуск O (N) рекурсивного алгоритма.
Наихудшим случаем будет что-то вроде O (N * M * L), где N равно длине списка, M - это уровень вложенности области, а L - количество символов в каждой области.
Мой совет - минимизировать количество используемого вами метапрограммирования на С ++.