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

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


Строго говоря, результат сравнения двух указателей, не принадлежащих одному массиву, не определен, но многие компиляторы на это не жалуются... Тем больше причин сделать все так, как положено. Спасибо Натану Майерсу (Nathan Myers) за предоставленный пример.

просто сравнивает адресаМ) Вероятно, вас интересует, почему мы указываем объявление using вместо директивы using namespace std? Потому что некоторые компиляторы автоматически включают заголовочные файлы, содержащие std::min(), и эта версия будет конфликтовать с именем нащей функции min().

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

tempiate<typename Т>

const Т& minCconst Т& а. const Т& Ь. const Т& с):

Специализации этого шаблона будут сгенерированы только для вызовов min() с тремя однотипными аргументами.

Получение адреса сгенерированного шаблона функции

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

: СОБ:TempiateFunctionAddress.срр {-mwcc}

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

template <typename Т> void f(T*) {}

void hCvoid (*pf)(int*)) {}

template <typename T> void gCvoid (*pf)(T*)) {}

int mainO { Полная спецификация типа: h(&f<int>): Вычисление типа: h(&f):

Полная спецификация типа: g<int>(&f<int>):

Автоматическое определение типа: g(&f<int>):

Неполная (но достаточная) спецификация типа g<int>(&f): } III:-

В этом примере стоит обратить внимание на ряд моментов. Во-первых, даже при использовании шаблонов сигнатуры должны совпадать. Функция h() получает указатель на функцию с аргументом int*, возвращающую void, и эта сигнатура должна быть сгенерирована шаблоном f(). Во-вторых, функция, получающая указатель на функцию, сама может быть шаблоном, как д().

Функция main О также показывает, как автоматически определяются типы. При первом вызове h() явно указано, что аргумент f() является шаблоном, но так как в соответствии с объявлением h() эта функция должна получать адрес функции



В частности, информацию о типах, закодированную в украшенных именах функций.

с параметром int*, компилятор мог бы и сам придти к этому выводу. В случае с д() возникает еще более интересная ситуация, в которой участвуют два щаблона. Компилятор не может определить тип без исходных данных, но если f() или д() передается int, остальное можно вычислить.

Другая нетривиальная проблема возникает при передаче в качестве параметров функций tolower и toupper, определенных в файле <cctype>. Например, эти функции могут использоваться в сочетании с алгоритмом transform (см. следующую главу) для преобразования строки к нижнему или верхнему регистру. Будьте осторожны: у этих функций имеется несколько определений. Наивное рещение выглядит примерно так:

Переменная s относится к типу stcl::string transform(s.beg1n(). s.endO. s.beginO. tolower);

Алгоритм transform применяет свой четвертый параметр (tolower в данном примере) к каждому символу s и помещает результат обратно в s. Таким образом, все символы S заменяются своими эквивалентами в нижнем регистре. Но в том виде, в котором эта команда приведена выще, она может и не работать! Например, в следующем контексте произойдет неудача:

; C05;FailedTransform.cpp {-хо}

#1 ncl ude <algorithm>

#1 ncl ude <cctype>

#incl ude <iostream>

#include <string>

using namespace std;

int mainO { string s( LOWER );

transf orm( s. begi n(). s. endO. s. begi n(). tol ower); cout s endl; } III:-

Даже если компиляция пройдет успешно, это все равно ошибка. Дело в том, что в заголовке <iostream> также объявляются версии tolower() и toupper() с двумя аргументами:

template <class charT> charT toupper(charT с. const locale& loc): template <class charT> charT tolower(charT c. const locale& loc):

Эти шаблоны функций получают второй аргумент типа locale. Компилятор не может определить, какую версию tolower() он должен использовать - с одним аргументом, определенную в <cctype>, или приведенную выше. Проблема (почти) решается преобразованием типа в вызове tranform (вспомните, что tolower() и toupper() работают с int вместо char):

transform(s.begi nO,s.end().s.begin() static cast<int (*)(int)>(tolower));

Преобразование типа однозначно указывает, что в программе должна использоваться версия tolower() с одним аргументом. На некоторых компиляторах такое решение работает, но это без гарантии. Дело в том, что для функций, унаследованных из языка С, реализации библиотеки позволено задействовать компоновку С (то есть не включать в имена функций дополнительную информацию, характерную для имен функций С++). В этом случае попытка преобразования завер-



Вообще говоря, компиляторы С++ могут вводить новые имена по своему усмотрению. К счастью, большинство компиляторов не объявляет неиспользуемые имена.

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

Проблема решается вызовами tolower() в однозначном контексте. Например, вы можете написать функцию strTolower() и поместить ее в отдельный файл без включения заголовка <iostream>:

: C05:StrTolower.cpp {0} {-mwcc} linclude <algorithm> linclude <cctype> linclude <string> using namespace std:

string strTolowerCstring s) {

transformCs.beginO, s.endO. s.beginO. tolower):

return s: } III:-

Файл не включает заголовочный файл <iostream>, поэтому компилятор в этом контексте не включает двухаргументную версию tolower(), и проблем не возникает. Далее новая функция используется обычным образом:

: СОБ:Tolower.срр {-mwcc} {L} StrTolower linclude <algorithm> linclude <cctype> linclude <iostream> linclude <string> using namespace std: string StrTolower(string):

int mainO {

string sCLOWER ):

cout strTolower(s) endl: } III:-

B другом решении создается функция-оболочка, которая явно вызывает правильную версию tolower():

: C05:ToLower2.cpp {-mwcc} linclude <algorithm> linclude <cctype> linclude <iostream> linclude <string> using namespace std:

tempiate<cl ass charT> CharT strTolower(charT c) { return tolower(c): Вызов версии с одним аргументом

int mainO { string sCLOWER ):

transformCs. begi nO.s.endO.s. begi nO .&strTolower<char>): cout s endl: } /:-



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

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