Во-первых, отказ от ответственности: я думаю, что , о котором вы спрашиваете, - это не только метапрограммирование шаблонов, но и общее программирование. Эти два понятия тесно связаны, и нет точного определения того, что каждый из них охватывает. Короче говоря, метапрограммирование шаблонов - это, по сути, написание программы с использованием шаблонов, которая оценивается во время компиляции. (что делает его полностью свободным во время выполнения. Ничего не происходит. Значение (или, чаще, тип) уже вычислено компилятором и доступно как константа (либо константная переменная, либо перечисление), либо как typedefвложенный в класс (если вы использовали его для «вычисления» типа).
Общее программирование использует шаблоны и, при необходимости, метапрограммирование шаблонов, чтобы создать общий код, который работает так же (и без потерь). в производительности), со всеми и любым типом. Я собираюсь использовать примеры обоих в следующем.
Обычное использование для шаблонного метапрограммирования состоит в том, чтобы позволить типам использоваться в универсальном программировании, даже если они былине предназначен для этого.
Поскольку метапрограммирование шаблонов технически происходит полностью во время компиляции, ваш вопрос немного более актуален для общего программирования, которое все еще происходит во время выполнения, но эффективно, потому что оно может быть специализированным дляточные типы, с которыми он используется во время компиляции.
В любом случае ...
Зависит от того, как вы определяете «эквивалентный код C».
Хитрость в метапрограммировании шаблонов (или в общем программировании в целом) заключается в том, что он позволяет перенести много вычислений на компиляцию. время, и это позволяет гибкий, параметризованный код, который так же эффективен, как жестко закодированные значения.
Код, отображаемый здесь , например, вычисляет число в последовательности Фибоначчи во время компиляции.
Код C ++ 'unsigned long fib11 = fibonacci<11uL>::value
' опирается на метапрограмму шаблона, определенную в этой ссылке, и так же эффективен, как и код C 'unsigned long fib11 = 89uL
'. Шаблоны оцениваются во время компиляции, давая константу, которая может быть назначена переменной. Таким образом, во время выполнения код фактически идентичен простому присваиванию.
Так что, если это «эквивалентный код C», производительность остается той же. Если эквивалентный код C является «программой, которая может вычислять произвольные числа Фибоначчи, применяемые для поиска 11-го числа в последовательности», то версия C будет намного медленнее, поскольку она должна быть реализована как функция, которая вычисляет значениево время выполнения. Но это «эквивалентный C-код» в том смысле, что это C-программа, которая демонстрирует ту же гибкость (это не просто жестко закодированная константа, а фактическая функция, которая может возвращать любое число в Фибоначчипоследовательность).
Конечно, это не часто полезно. Но это в значительной степени канонический пример шаблонного метапрограммирования.
Более реалистичным примером общего программирования является сортировка.
В C у вас есть стандартная библиотечная функция qsort
, принимающая массив иуказатель функции компаратора. Вызов этого указателя функции не может быть встроенным (кроме как в тривиальных случаях), потому что во время компиляции неизвестно, какая функция будет вызываться.
Конечно, альтернативой является рукописныйФункция сортировки, разработанная для вашего конкретного типа данных.
В C ++ эквивалентом является шаблон функции 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()
.
КонецВ результате функция C ++ std::sort
является точно такой же эффективной, как и ваша кодированная вручную реализация в C того же алгоритма сортировки.
Опять же, если это "эквивалентный код C"», то производительность такая же. Но если «эквивалентный код C» является «обобщенной функцией сортировки, которая может применяться к любому типу и допускает пользовательские компараторы», то универсальная версия программирования на C ++ значительно эффективнее.
Это действительно хитрость. Общее программирование и шаблонное метапрограммирование не "быстрее, чем C". Это методы достижения общего, многократно используемого кода , который так же быстр, как с ручным кодированием, и жестко закодированного C
. Это способ получить лучшее из обоих миров. Производительность жестко закодированных алгоритмов, а также гибкость и возможность повторного использования общих параметризованных.