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

inline MyVectorSum,MyVector >

operator+(const MyVector& left,

          const MyVector& right) {

  return

    MyVectorSum,MyVector >

      (left,right);

}

template

inline

MyVectorSum,

            MyVector >

operator+(const MyVectorSum& left,

          const MyVector& right) {

  return MyVectorSum,

          MyVector >

    (left, right);

}

// Convenience functions for the test program below

template

void init(MyVector& v) {

  for (size_t i = 0; i < N; ++i)

    v[i] = rand() % 100;

}

template

void print(MyVector& v) {

  for (size_t i = 0; i < N; ++i)

    cout << v[i] << ' ';

  cout << endl;

}

int main() {

  MyVector v1;

  init(v1);

  print(v1);

  MyVector v2;

  init(v2);

  print(v2);

  MyVector v3;

  v3 = v1 + v2;

  print(v3);

  // Now supported:

  MyVector v4;

  v4 = v1 + v2 + v3;

  print(v4);

  MyVector v5;

  v5 = v1 + v2 + v3 + v4;

  print(v5);

} ///:~.

Instead of committing ahead of time which types the arguments of a sum will be, we let the template facility deduce them with the template arguments, Left and Right. The MyVectorSum template takes these extra two parameters so it can represent a sum of any combination of pairs of MyVector and MyVectorSum. Note also that the assignment operator this time is a member function template. This also allows any <T, N> pair to be coupled with any <Left, Right> pair, so a MyVector object can be assigned from a MyVectorSum holding references to any possible pair of the types MyVector and MyVectorSum. As we did before, let’s trace through a sample assignment to understand exactly what takes place, beginning with the expression.

v4 = v1 + v2 + v3;

Since the resulting expressions become quite unwieldy, in the explanation that follows, we will use MVS as shorthand for MyVectorSum, and will omit the template arguments.

The first operation is v1+v2, which invokes the inline operator+( ), which in turn inserts MVS(v1, v2) into the compilation stream. This is then added to v3, which results in a temporary object according to the expression MVS(MVS(v1, v2), v3). The final representation of the entire statement is.

v4.operator+(MVS(MVS(v1, v2), v3));

This transformation is all arranged by the compiler and explains why this technique carries the moniker "expression templates"; the template MyVectorSum represents an expression (an addition, in this case), and the nested calls above are reminiscent of the parse tree of the left-associative expression v1+v2+v3.

An excellent article by Angelika Langer and Klaus Kreft explains how this technique can be extended to more complex computations.[76] 

<p>Template compilation models</p>

You have certainly noticed by now that all our template examples place fully-defined templates within each compilation unit. (For example, we place them completely within single-file programs or in header files for multi-file programs.) This runs counter to the conventional practice of separating ordinary function definitions from their declarations by placing the latter in header files and the function implementations in separate (that is, .cpp) files. Everyone knows the reason for this separation: non-inline function bodies in header files can lead to multiple function definitions, which results in a linker error. A nice side benefit of this approach is that vendors can distribute pre-compiled code along with headers so that users cannot see their function implementations, and compile times are shorter since header files are smaller.

<p>The inclusion model</p>

Templates, on the other hand, are not code, per se, but instructions for code generation; only template instantiations are real code. When a compiler has seen a complete template definition during a compilation and then encounters a point of instantiation for that template in the same translation unit, it must deal with the fact that an equivalent point of instantiation may be present in another translation unit. The most common approach consists in generating the code for the instantiation in every translation unit and let the linker weed out duplicates. That particular approach also works well with inline functions that cannot be inlined and with virtual function tables, which is one of the reasons for its popularity. Nonetheless, several compilers prefer instead to rely on more complex schemes to avoid generating a particular instantiation more than once. Either way, it is the responsibility of the C++ translation system to avoid errors due to multiple equivalent points of instantiation.

Перейти на страницу:

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

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

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