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

1 ... 65 66 67 [ 68 ] 69 70 71 ... 196


friend Box operator+<>(const Вох<Т>&, const Вох<Т>&): friend ostreamS operator <>(ostreani&. const Box<T>&):

tempiate<cl ass T>

Box<T> operator+Cconst Box<T>& bl. const Box<T>& b2) { return Box<T>(bl.t + b2.t):

tempiate<c1ass T>

ostream& operator (ostream& os. const Box<T>& b) { return OS [ b.t ]:

int mainO {

Box<int> bid). b2(2):

cout bl + b2 endl: [3] cout bl + 2 endl: Автоматические преобразования отсутствуют! } III:-

В этом примере определяются внешние операторы сложения и вывода в поток. В функции mainQ проявляется главный недостаток такого подхода: автоматические преобразования (как в выражении Ы+2) становятся невозможными, потому что они не поддерживаются шаблонами. При внутреннем ( нешаблонном ) определении программа получается короче и надежнее:

: С05:Вох2.срр

Определение нешаблонных операторов linclude <iostream> using namespace std:

tempiate<class T> class Box {

T t: public:

Box(const T& theT) : t(theT) {}

friend Box operator+(const Box<T>& bl. const Box<T>& b2) { return Box<T>(bl.t + b2.t):

friend ostreamS operator (ostream& os. const Box<T>& b) { return OS [ b.t ]:

int mainO {

Box<int> bid). b2(2):

cout bl + b2 endl: [3]

cout bl + 2 endl: [3] } III:-

Поскольку операторы являются обычными функциями (перегружаемыми для каждой специализации Box - в данном случае для int), неявные преобразования действуют нормально, и выражение bl+2 допустимо.

Учтите, что один тип не может быть объявленным дружественным по отношению к Box и вообще какому-либо шаблону класса. Речь идет о типе Т, а вернее, о том типе, по которому параметризован шаблон класса. Насколько нам известно, не существует сколько-нибудь обоснованных причин для такого запрета, но пока объявление friend class Т считается недопустимым и вызывает ошибку компиляции.



Идиомы программирования с применением шаблонов

Язык является орудием мышления, поэтому новые языковые возможности обычно порождают новые приемы. В этом разделе мы рассмотрим ряд распространенных идиом, появившихся с момента включения шаблонов в язык С++.

Характеристики

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

Простейшим примером шаблона характеристик является класс numeric limits, определяемый в файле <limits>. Определение основного щаблона выглядит так:

tempiate<class Т> class numericjimits { public:

static const bool is specialized - false: static T minO throwO;

Вы можете точно указать, какие специализации шаблона являются друзьями класса. В примерах предыдушего раздела дружественной была только специализация шаблона функции f с тем же типом, по которому специализировался шаблон Friendly. Например, дружественной для класса Friendly<int> была только специализация f<int>(const Friendly<int>&). Поэтому параметр шаблона Friendly использовался для специализации f в объявлении friend. При желании мы могли бы сделать конкретную фиксированную специализацию f дружественной для всех экземпляров Friendly:

Внутри Friendly:

friend void f<>(const Friendly<doub1e>&);

После замены Т на double специализация f для double получает доступ ко всем закрытым и защищенным членам любой специализации Friendly. Как и прежде, специализация f<double>() создается лишь при явном вызове.

Аналогично, если объявить нешаблонную функцию без параметров, зависящих от Т, эта функция становится дружественной для всех специализаций Friendly:

Внутри Friendly:

friend vote g(int): g(int) является другом

всех специализаций Friendly

Как всегда, неуточненная функция g(int) должна определяться на уровне файла (в пространстве имен, содержащем Friendly).

Также можно сделать все специализации f дружественными для всех специализаций Friendly при помощи так называемых дружественных шаблонов:

tempiate<class Т> class Friendly { tempiate<class U> friend void f<>(const Friendly<U>&);

Поскольку аргумент в объявлении дружественного шаблона не зависит от Т, в этих дружественных отношениях допускаются любые комбинации Т и U. Дружественные шаблоны, как и вложенные, могут использоваться внутри нешаблонных классов.



static Т тахО throwO:

static const int digits = 0:

static const int digitslO = 0:

static const bool is signed = false:

static const bool isjnteger = false:

static const bool is exact = false:

static const int radix = 0:

static T epsilonO throwO:

static T round error() throwO:

static const int min exponent = 0:

static const int rnin exponentlO = 0:

static const int max exponent = 0:

static const int max exponentlO = 0:

static const bool hasjnfinity = false:

static const bool has quiet NaN = false:

static const bool has signaling NaN = false:

static const f1oat denorm style has denorm = denorm absent:

static const bool has denorm loss = false:

static T infinit.yO throwO:

static T quiet NaN() throwO:

static T signaling NaN() throwO:

static T denorm min() throwO:

static const bool is iec559 = false:

static const bool is bounded = false:

static const bool is modulo = false:

static const bool traps = false:

static const bool tinyness before = false:

static const float round style round style = round toward zero:

В заголовке <limits> определяются специализации для всех основных числовых типов (переменная is specialized равна true). Например, основание системы счисления для экспоненты в вещественном типе double может быть получено при помощи выражения numeric limits<double>::radix. Наименьшее доступное целое число определяется выражением numeric limits<int>::min(). Не все члены numeric limits относятся ко всем основным типам (например, функция epsilon() имеет смысл только для вещественных типов).

Значения, которые всегда являются целыми, определяются в виде статических переменных numeric limits. Те, которые могут оказаться нецелыми (например, минимальное значение float), реализуются в виде статических подставляемых функций. Такое различие объясняется тем, что С++ позволяет инициализировать в определении класса только целочисленные статические переменные.

В главе 3 было показано, как при помощи классов характеристик управлять средствами обработки символьных данных в строковых классах. Классы std::string и std::wstring являются специализациями шаблона std::basic string, который определяется следующим образом:

tempiate<class charT, class traits = char traits<charT>. class allocator = allocator<charT> > class basic string:

Параметр шаблона charT представляет базовый тип символов, обычно это char или wchar t. Основной шаблон char traits обычно остается пустым, а специализации для char и wchar t предоставляются стандартной библиотекой. Далее приведена спецификация специализации char traits<char> в соответствии со стандартом С++:



1 ... 65 66 67 [ 68 ] 69 70 71 ... 196

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