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

As you can see, you can partially specify template parameters according to whether they are pointer types, or whether they are equal. When the T* specialization is used, such as is the case in line 5, T itself is not the top-level pointer type that was passed—it is the type that the pointer refers to (float, in this case). The T* specification is a pattern to allow matching against pointer types. If you were to use int** as the first template argument, T would be int*. Line 8 is ambiguous because having the first parameter as an int vs. having the two parameters equal are independent issues—one is not more specialized than the other. Similar logic applies to lines 9 through 12.

<p>A practical example</p>

You can easily derive from a class template, and you can create a new template that instantiates and inherits from an existing template. If the vector template does most everything you want, for example, but in a certain application you’d also like a version that can sort itself, you can easily reuse the vector code. The following example derives from vector and adds sorting.

//: C05:Sorted.h

// Template specialization

#ifndef SORTED_H

#define SORTED_H

#include

#include

template

class Sorted : public std::vector {

public:

  void sort();

};

template

void Sorted::sort() { // A simple sort

  for(int i = size(); i > 0; i--)

    for(int j = 1; j < i; j++)

      if(at(j-1) > at(j)) {

        T t = at(j-1);

        at(j-1) = at(j);

        at(j) = t;

      }

}

// Partial specialization for pointers:

template

class Sorted : public std::vector {

public:

  void sort();

};

template

void Sorted::sort() {

  for(int i = size(); i > 0; i--)

    for(int j = 1; j < i; j++)

      if(*at(j-1) > *at(j)) {

        T* t = at(j-1);

        at(j-1) = at(j);

        at(j) = t;

      }

}

// Full specialization for char*

// (Made inline here for convenience –

//  normally would place function body in separate file

//  and only leave declaration here)

template<>

inline void Sorted::sort() {

  for(int i = size(); i > 0; i--)

    for(int j = 1; j < i; j++)

      if(std::strcmp(at(j-1), at(j)) > 0) {

        char* t = at(j-1);

        at(j-1) = at(j);

        at(j) = t;

      }

}

#endif // SORTED_H ///:~

The Sorted template imposes a restriction on all but one of the classes for which it is instantiated: they must contain a > operator. It works correctly only with non-pointer objects (including objects of built-in types). The full specialization compares the elements using strcmp( ) to sort vectors of char* according to the null-terminated strings to which they refer.

Here’s a driver for Sorted.h that uses the randomizer introduced earlier in the chapter:.

//: C05:Sorted.cpp

//{bor} (because of bitset in Urand.h)

// Testing template specialization

#include

#include

#include "Sorted.h"

#include "Urand.h"

using namespace std;

#define asz(a) (sizeof a / sizeof a[0])

char* words[] = {

  "is", "running", "big", "dog", "a",

};

char* words2[] = {

  "this", "that", "theother",

};

int main() {

  Sorted is;

  Urand<47> rand;

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

    is.push_back(rand());

  for(size_t i = 0; i < is.size(); i++)

    cout << is[i] << ' ';

  cout << endl;

  is.sort();

  for(size_t i = 0; i < is.size(); i++)

    cout << is[i] << ' ';

  cout << endl;

  // Uses the template partial specialization:

  Sorted ss;

  for(size_t i = 0; i < asz(words); i++)

    ss.push_back(new string(words[i]));

  for(size_t i = 0; i < ss.size(); i++)

    cout << *ss[i] << ' ';

  cout << endl;

  ss.sort();

  for(size_t i = 0; i < ss.size(); i++) {

    cout << *ss[i] << ' ';

    delete ss[i];

  }

  cout << endl;

  // Uses the full char* specialization:

  Sorted scp;

  for(size_t i = 0; i < asz(words2); i++)

    scp.push_back(words2[i]);

  for(size_t i = 0; i < scp.size(); i++)

    cout << scp[i] << ' ';

  cout << endl;

  scp.sort();

  for(size_t i = 0; i < scp.size(); i++)

    cout << scp[i] << ' ';

  cout << endl;

} ///:~

Each of the template instantiations above uses a different version of the template. Sorted uses the primary template. Sorted uses the partial specialization for pointers. Last, Sorted uses the full specialization for char*. Without this full specialization, you could be fooled into thinking that things were working correctly because the words array would still sort out to "a big dog is running" since the partial specialization would end up comparing the first character of each array. However, words2 would not sort correctly.

<p>Preventing template code bloat</p>

Whenever a class template is instantiated, the code from the class definition for the particular specialization is generated, along with all the member functions that are called in the program. Only the member functions that are actually called are generated. This is a good thing, as the following program makes clear:.

//: C05:DelayedInstantiation.cpp

// Member functions of class templates are not

// instantiated until they're needed.

class X {

public:

  void f() {}

};

class Y {

public:

  void g() {}

};

template class Z {

  T t;

public:

  void a() { t.f(); }

  void b() { t.g(); }

};

int main() {

  Z zx;

  zx.a(); // Doesn't create Z::b()

  Z zy;

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

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

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

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

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

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

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

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

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