Программирование >>  Разработка устойчивых систем 

1 ... 56 57 58 [ 59 ] 60 61 62 ... 196


tempiate<typename T>

std::string toString(const T& t) {

std::ostringstream s:

s t:

return s.strO:

#endif STRINGCONV H /:-

Эти шаблоны обеспечивают преобразование в std::string и обратно для любого типа, для которого определен потоковый оператор или соответственно. Ниже приведена тестовая программа, в которой используется тип complex из стандартной библиотеки:

: C05:StringConvTest.cpp #include <complex> linclude <iostream> linclude StringConv.h using namespace std:

int mainO { int i = 1234:

cout i == \ toString(i) \ endl float X = 567.89:

cout x == \ toString(x) \ endl complex<float> cd.O. 2.0): cout c == \ toString(c) \ endl cout endl:

i = fromString<int>(string( 1234 )): cout i == i endl: X = fromString<float>(string( 567.89 )): cout x == X endl:

с = fromString< complex<float> >(string( (1.0,2.0) )): cout c == с endl: } /:-

Результат выполнения программы вполне предсказуем:

i == 1234 X == 567.89 с == (1.2)

i == 1234 X == 567.89 с =- (1.2)

: C05:StringConv.h

Шаблоны функций для преобразования в строку и обратно #1fndef STRINGCONV H #define STRINGCONV H #1nclude <string> #1 nclude <sstream>

tempiate<typename T>

T fromString(const std::string& s) {

std::istringstream is(s):

T t:

is t: return t:



int mainO { int a[10][20]:

initl<10.20>(a): Обязательно задаются размеры init2(a); Автоматическое определение размеров

} /:-

Обратите внимание: при каждой специализации fromString() в вызов включается параметр шаблона. Если у вас имеется шаблон функции, параметры которого определяют типы как параметров функции, так и ее возвращаемого значения, очень важно начать с объявления параметра для типа возвращаемого значения. В противном случае вам придется обязательно указывать типы параметров функции при перечислении параметров шаблона. Для примера рассмотрим шаблон функции, знакомый многим по книгам Страуструпа (Stroustrup):

: C05:Impl1citCast.cpp tempiate<typename R. typename P> R implic1t cast(const P& p) { return p:

int mainO { int i = 1:

float X = 1mplicit cast<float>(i): int j = implic1t cast<int>(x); char* p = implicit cast<char*>(i); } III-

Если поменять местами R и P в списке параметров, находящемся во второй строке файла, программа не будет компилироваться, потому что тип возвращаемого значения останется неизвестным (первый параметр шаблона будет соответствовать типу параметра функции). Последняя (закомментированная) строка недопустима, поскольку стандартного преобразования int в char* не существует. Вызов implicit cast выявляет естественные преобразования типов в вашей программе.

Если действовать достаточно осмотрительно, вы даже сможете вычислить размеры массивов. В следующем примере эти вычисления выполняются в шаблоне функции инициализации массива (initZ):

: C05:ArrayS1ze.cpp #include <cstddef> using std::s1ze t:

tempiate<size t R. size t C. typename T> void InitKT a[R][C]) { for (size t 1 =0: 1 < R: ++i) for (size t j = 0: j < C: ++j) a[i][j] = TO:

tempiate<s1ze t R. s1ze t C. class T> void 1nit2(T (&a)[R][C]) { Ссылочный параметр for (s1ze t 1 = 0: i < R: for (size t j = 0: j < C: a[1][j] = TO:



using std using std using std

strcmp: cout: endl:

tempiate<typename T> const T& min(const T& a. const T& b) { return (a < b) ? a : b:

const char* min(const char* a. const char* b) { return (strcmp(a. b) < 0) ? a : b:

double min(double x. double y) { return (x < y) ? X : y:

int mainO {

const char *s2 = say \ Ni-!\ . *sl = knights who :

cout mind. 2) endl: 1: 1 (шаблон)

cout mind.O. 2.0) endl: 2: 1 (double)

cout mind. 2.0) endl: 3: 1 (double)

cout min(sl. s2) endl: 4: knights who (const char*)

cout min<>(sl. s2) endl: 5: say Ni-!

(шаблон)

} /:-

Помимо шаблона функции в этой программе определяются две нешаблонные функции: версия min() для строк С и для double. Если бы шаблона не было, то для первой строки была бы вызвана double-версия min(), так как су шествует стандартное преобразование int в double. Однако шаблон может сгенерировать int-версию, которая обеспечивает лучшее совпадение; именно это и происходит в программе. Вызов во второй строке точно совпадает с double-версией, а в третьей строке снова вызывается та же функция, при этом 1 автоматически преобразуется в 1.0. В четвертой строке напрямую вызывается версия min() для const char*. В строке 5 мы заставляем компилятор задействовать шаблон, присоединяя пустую пару угловых скобок к имени функции. Компилятор генерирует специализацию для const char* и использует ее (в этом можно убедиться по неправильному ответу - компилятор

Размеры массивов не являются частью типа параметра функции, если только этот параметр не передается в виде указателя или ссылки. Шаблон функции initZ объявляет а ссылкой на двумерный массив, поэтому его размеры R и С определяются автоматически. Таким образом, initZ является удобным средством инициализации двумерных массивов произвольного размера. В шаблоне initl массив не передается по ссылке, поэтому размер приходится задавать явно (хотя параметр типа все равно может быть определен автоматически).

Перегрузка шаблонов функций

Одноименные шаблоны функций могут перегружаться так же, как и обычные функции. Обрабатывая вызов функции в программе, компилятор должен решить, шаблон или обычная функция лучше всего подходит для данного вызова.

Давайте добавим к уже рассматривавшемуся шаблону функции min() несколько обычных функций:

: C05:M1nTest.cpp #1nclude <cstr1ng> #1nclude <iostream>



1 ... 56 57 58 [ 59 ] 60 61 62 ... 196

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика