Ответ 1
Во-первых, отказ от ответственности: То, о чем я думаю, вы спрашиваете, это не просто метапрограммирование шаблона, но и общее программирование. Эти два понятия тесно связаны, и нет точного определения того, что каждый из них охватывает. Но, короче говоря, метапрограммирование шаблонов, по существу, записывает программу с использованием шаблонов, которая оценивается во время компиляции. (что делает его полностью бесплатным во время выполнения. Ничего не происходит. Значение (или, чаще всего, тип) уже было вычислено компилятором и доступно как константа (либо константная переменная, либо перечисление), либо как typedef вложенные в класс (если вы использовали его для "вычисления" типа).
В общем программировании используются шаблоны и, при необходимости, метапрограммирование шаблонов, чтобы создать общий код, который работает одинаково (и без потери производительности), со всеми и любыми типами. Я собираюсь использовать примеры обоих в следующем.
Общепринятое использование метапрограммирования шаблонов - это возможность использования типов в общем программировании, даже если они не предназначены для него.
Поскольку метапрограммирование шаблонов технически происходит полностью во время компиляции, ваш вопрос немного более важен для общего программирования, который все еще имеет место во время выполнения, но эффективен, поскольку он может быть специализирован для точных типов, с которыми он использовался при компиляции -time.
В любом случае...
Зависит от того, как вы определяете "эквивалентный код C" .
Фокус метапрограммирования шаблонов (или общего программирования в целом) заключается в том, что он позволяет переносить множество вычислений во время компиляции и позволяет гибкий, параметризованный код, который так же эффективен, как и жестко заданные значения.
Представленный код здесь, например, вычисляет число в последовательности фибоначчи во время компиляции.
Код С++ 'unsigned long fib11 = fibonacci<11uL>::value
', опирается на метапрограмму шаблона, определенную в этой ссылке, и эффективен как код C 'unsigned long fib11 = 89uL
'. Шаблоны оцениваются во время компиляции, давая константу, которая может быть назначена переменной. Таким образом, во время выполнения код фактически идентичен простому назначению.
Итак, если это "эквивалентный код C" , производительность одинакова. Если эквивалентный C-код - это "программа, которая может вычислять произвольные числа фибоначчи, применяемые для поиска 11-го числа в последовательности", то версия C будет намного медленнее, поскольку она должна быть реализована как функция, которая вычисляет значение во время выполнения. Но это "эквивалентный C-код" в том смысле, что он представляет собой программу на C, которая обладает такой же гибкостью (это не просто фиксированная константа, а фактическая функция, которая может возвращать любое число в последовательности фибоначчи).
Конечно, это не всегда полезно. Но это в значительной степени канонический пример метапрограммирования шаблонов.
Более реалистичный пример универсального программирования сортирует.
В C вы имеете стандартную библиотечную функцию qsort
, берущую массив и указатель функции компаратора. Вызов этого указателя функции не может быть встроен (за исключением тривиальных случаев), потому что во время компиляции неизвестно, какая функция будет вызываться.
Конечно, альтернативой является ручная сортировка, предназначенная для вашего конкретного типа данных.
В С++ эквивалентным является шаблон функции std::sort
. Он также принимает компаратор, но вместо этого он является указателем на функцию, это объект функции, выглядящий следующим образом:
struct MyComp {
bool operator()(const MyType& lhs, const MyType& rhs) {
// return true if lhs < rhs, however this operation is defined for MyType objects
}
};
и это может быть включено. Функция std::sort
передается аргумент шаблона, поэтому он знает точный тип компаратора и поэтому знает, что функция компаратора является не только неизвестным указателем функции, но MyComp::operator()
.
Конечным результатом является то, что функция С++ std::sort
точно такая же эффективная, как ваша ручная реализация в C того же алгоритма сортировки.
Итак, если это "эквивалентный код C" , то производительность одинакова. Но если "эквивалентный C-код" представляет собой "обобщенную функцию сортировки, которая может быть применена к любому типу и допускает определяемые пользователем компараторы", то общая программная версия на С++ значительно эффективнее.
Это действительно трюк. Общее программирование и метапрограммирование шаблонов не являются "быстрее, чем C". Это методы для получения общего кода многократного использования, который работает так же быстро, как и ручной код, и жестко закодированный C
Это способ получить лучшее из обоих миров. Производительность жестко запрограммированных алгоритмов, гибкость и возможность повторного использования общих, параметризованных.