Читаем Thinking In C++. Volume 2: Practical Programming полностью

When the compiler attempts to instantiate Factorial<12>, it finds it must also instantiate Factorial<11>, which requires Factorial<10>, and so on. Eventually the recursion ends with the specialization Factorial<1>, and the computation unwinds. Eventually, Factorial<12>::val is replaced by the integral constant 479001600, and compilation ends. Since all the computation is done by the compiler, the values involved must be compile-time constants, hence the use of enum.[66] When the program runs, the only work left to do is print that constant followed by a newline. To convince yourself that a specialization of Factorial results in the correct compile-time value, you could use it as an array dimension, such as:.

double nums[Factorial<5>::val];

assert(sizeof nums == sizeof(double)*120);

<p>Compile-time programming</p>

So what was meant to be a convenient way to perform type parameter substitution turned out to be a mechanism to support compile-time programming. Such a program is called a template metaprogram (since you’re in effect "programming a program"), and it turns out that you can do quite a lot with such a beast. In fact, template metaprogramming is Turing complete because it supports selection (if-else) and looping (through recursion); so theoretically you can perform any computation with it.[67] The factorial example above shows how to implement repetition; write a recursive template and provide a stopping criterion via a specialization. The following example shows how to compute Fibonacci numbers at compile time by the same technique.

//: C05:Fibonacci.cpp

#include

using namespace std;

template

struct Fib {

   enum {val = Fib::val + Fib::val};

};

template<>

struct Fib<1> {

   enum {val = 1};

};

template<>

struct Fib<0> {

   enum {val = 0};

};

int main() {

   cout << Fib<5>::val << endl;   // 6

   cout << Fib<20>::val << endl;  // 6765

} ///:~.

Fibonacci numbers are defined mathematically as:

The first two cases lead to the template specializations above, and the rule in the third line becomes the primary template.

<p>Compile-time looping</p>

To compute any loop in a template metaprogram, it must first be reformulated recursively. For example, to raise the integer n to the power p, instead of using a loop such as in the following lines:.

int val = 1;

while (p--)

  val *= n;

you would have to think of it as a recursive procedure:

int power(int n, int p) {

  return (p == 0) ? 1 : n*power(n, p - 1);

}

This can now be easily rendered as a template metaprogram as follows:

//: C05:Power.cpp

#include

using namespace std;

template

struct Power {

  enum {val = N * Power::val};

};

template

struct Power {

  enum {val = 1};

};

int main() {

  cout << Power<2, 5>::val << endl;  // 32

} ///:~

Note that we need to use a partial specialization for the stopping condition, since the value N is still a free template parameter. This program only works for non-negative powers, of course.

The following metaprogram adapted from Czarnecki and Eisenecker[68] is interesting in that it uses a template template parameter, and simulates passing a function as a parameter to another function, which "loops through" the numbers 0..n.

//: C05:Accumulate.cpp

// Passes a "function" as a parameter at compile time

#include

using namespace std;

// Accumulates the results of F(0)..F(n)

template class F>

struct Accumulate {

   enum {val = Accumulate::val + F::val};

};

// The stopping criterion (returns the value F(0))

template class F>

struct Accumulate<0, F> {

   enum {val = F<0>::val};

};

// Various "functions":

template

struct Identity {

   enum {val = n};

};

template

struct Square {

   enum {val = n*n};

};

template

struct Cube {

   enum {val = n*n*n};

};

int main() {

   cout << Accumulate<4, Identity>::val << endl; // 10

   cout << Accumulate<4, Square>::val << endl;   // 30

   cout << Accumulate<4, Cube>::val << endl;     // 100

} ///:~.

The primary Accumulate template attempts to compute the sum F(n)+F(n‑1)…F(0). The stopping criterion is obtained by a partial specialization, which "returns" F(0). The parameter F is itself a template, and acts like a function as in the previous examples in this section. The templates Identity, Square, and Cube compute the corresponding functions of their template parameter that their names suggest. The first instantiation of Accumulate in main( ) computes the sum 4+3+2+1+0, because the Identity function simply "returns" its template parameter. The second line in main( ) adds the squares of those numbers (16+9+4+1+0), and the last computes the sum of the cubes (64+27+8+1+0).

<p>Loop unrolling</p>
Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных