Введение в метапрограммирование шаблона на C++ - Реальный пример

ОГЛАВЛЕНИЕ

Реальный пример

В качестве примера включен маленький класс, производящий общие вычисления CRC (циклические избыточные коды – набор простых хэш-алгоритмов). Класс использует набор параметров, определенных #define:d вверху заголовка. CRC выбраны для данной статьи, потому что алгоритмы CRC обычно используют таблицу поиска на базе набора параметров, делая пример похожим на исходную задачу.

Класс генерирует таблицу поиска с 256 записями во время компиляции. Реализация весьма проста, и комментариев в исходниках достаточно для объяснения использования класса. Иногда использовались макросы, где TMP было возможным решением. Причина в читабельности, являющейся важным фактором при выборе используемой техники.

Более подробное объяснение алгоритмов CRC ищите в книге Росса Н. Вильямса "Руководство по алгоритмам обнаружения ошибок CRC". В пример включена дословная копия текста.

При компиляции учтите, что исходники используют много динамической памяти компьютера. Предел распределения памяти увеличивается опцией компилятора '/Zm400'. Недостаток TMP в том, что оно доводит компьютер до предела.

Соглашения по программированию

Компилятор  терпеть не может, когда его неправильно используют, как описано выше. И он будет сопротивляться. Предупреждения и ошибки будут варьироваться от загадочных до C1001 – внутренняя ошибка компилятора. Меташаблонную программу нельзя отлаживать как исполняемую программу.

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

Общие советы

Так как шаблонные метапрограммы отчасти похожи на макросы, имена классов TMP пишутся заглавными буквами. Также задавайте максимально осмысленные имена. Основная причина для этого в том, что открытые переменные/функции обычно имеют неосмысленные имена (смотрите ниже). Класс TMP определяет операцию, а не функции-члены или переменные члены.

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

Имена переменных/функций

В классе TMP определяется одна из двух возможных открытых операций:

•    RESULT для шаблонов, вычисляющих значение
•    EXEC() для разворачивания цикла/упрощения функции.

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

Надо ли использовать TMP в программе?

Шаблонное метапрограммирование – прекрасная техника при верном применении. В то же время оно может привести к раздуванию кода и падению производительности. Ниже даны проверенные правила, когда применять TMP.

Используйте TMP, когда:

•    Макроса недостаточно. Нужно нечто более сложное, чем макрос, что должно разворачиваться перед компиляцией.
•    Используется рекурсивная функция с заранее заданным числом циклов. При этом издержек вызовов функций и установки переменных стека можно избежать, и время выполнения значительно уменьшается.
•    Используются циклы, которые можно развернуть во время компиляции. К примеру, алгоритмы хэша, такие как MD5 и SHA1, содержат строго определенные циклы обработки блоков, которые можно развернуть с помощью TMP.
•    При вычислении постоянных значений. Если в программе есть константы, зависящие от других констант, для них подойдет TMP.
•    Когда программа должны переноситься на другие платформы. В этом случае TMP может быть альтернативой макросам.

Не используйте TMP, когда:

•    Когда макрос подходит. В большинстве случаев макроса достаточно. Макрос проще понять, чем TMP.
•    Нужна маленькая исполняемая программа. Шаблоны вообще, а особенно TMP, увеличивают размер кода.
•    Программа уже долго компилируется. TMP существенно увеличивает время компиляции.
•    Жесткие сроки. Как сказано выше, компилятор недружелюбен при работе с шаблонными метапрограммами. Если вносимые изменения не являются простыми, вы избежите нескольких часов мучений.