Программирование >>  Полиморфизм без виртуальных функций в с++ 

1 ... 108 109 110 [ 111 ] 112 113 114 ... 144


типами (см. раздел 15.6.1), и вложенные шаблоны (см. раздел 15.9.3), можно было включить в язык сразу. Это бы несильно отразилось на сложности компилятора, а пользователям помогло. С другой стороны, я не предложил достаточной поддержки разработчикам компиляторов в плане инстанцирования шаблонов (см. раздел 15.10).

Предложение было передано на рассмотрение комитета ANSI/ISO по стандартизации. Правила привязки имен, механизм явного инстанцирования, ограничения на специализацию и явная квалификация вызовов шаблонов функций одобрены для включения в С-ы- на заседании комитета в Сан-Хосе в ноябре 1993 г. как часть общего плана совершенствования определения шаблонов.

15.3. Шаблоны классов

Ключевые конструкции излагались следующим образом [Stroustrup, 1988b]:

В С++ параметризованный тип называется шаблоном класса. Он описывает, как можно конструировать отдельные классы, точно так же, как сам класс описывает конструирование индивидуальных объектов. Шаблон класса вектора можно было бы объявить так:

template<class Т> class vector {

Т* v;

int SZ; public:

vector(int);

T& operator[](int);

T& elemdnt i) { return v[i]; }

Префикс teinplate<class T> дает понять, что объявляется шаблон и что внутри объявления будет использоваться аргумент Т типа type (тип, переданный при объявлении). После этого в области действия объявления шаблона Т можно использовать точно так же, как любое имя любого другого типа. Объявленные векторы допускается применять следующим образом:

vector<int> vl(20); vector<complex> v2{30);

typedef vector<complex> cvec; cvec - синоним для vector<complex>

cvec v3{40); v2 и v3 имеют один и тот же тип

void f{) {

vl[3] = 7;

v2[3] = v3.elem{4) = complex{7,8);

Пользоваться шаблонами не сложнее, чем классами. Полные имена экземпляров шаблона класса, такие как vector<int> или vector<complex>, легко читаются. Быть может, данная запись даже понятнее, чем нотация для массива встроенного типа: int [] исотр1ех[]. Если полное имя оказывается слишком длинным, то можно ввести сокращение с помощью

typedef.



Объявить шаблон класса лишь немного сложнее, чем сам класс. Ключевое слово class используется для того, чтобы обозначить аргументы типо type. С одной стороны, оно вполне подходит для этого, с другой - отпадает необходимость вводить новое ключевое слово. В данном контексте class означает любой тип , а не только тип, определенный пользователем .

Угловые скобки < . . . > используются вместо фигурных (...) с целью подчеркнуть иную природу аргументов шаблона, а также потому, что (...) используются в С++ слишком часто.

Ключевое слово template введено, чтобы объявления шаблонов находились с легкостью, а шаблоны классов и функций были обеспечены единым синтоксисом .

Шаблоны - это механизм генерирования типов. Сами по себе они не являются типами, никак не представлены во время исполнения, поэтому не оказывают влияния на модель размещения объекта в па.мяти.

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

Другими словами, механизм реализации параметризованных типов должен быть таким, чтобы програм.мист мог заменить обычные массивы стандартным библиотечным классом (см. раздел 8.5). Естественно, встроенные массивы по-прежне.му останутся в языке: они необходимы части пользователей и применяются в миллионах строк кода. Однако я хотел предложить эффективную альтернативу те.м, кто ценит удобство и безопасность типов больше совместимости.

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

15.3.1. Аргументы шаблонов, не являющиеся типами

Кроме аргументов-типов C+-I- допускает в шаблонах и аргументы, не являющиеся типами. Предполагалось, что они будут использоваться главным образом для задания раз.меров и верхних границ контейнерных классов. Например:

template<class Т, int i> class Buffer {

Т v[i];

int sz; public:

BufferO : sz(i) (}

...



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

Если бы аргументы, не являющиеся типами, не поддерживались, то пришлось бы передавать размер через тип массива, как в следующем примере:

template<class Т, class А> class Buf {

А v;

int sz; public:

BufO : sz{sizeof{A)/sizeof(T)) {} . . .

Buf<int, int[700]> b;

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

В первоначальном проекте в качестве аргументов не могли выступать шаблоны и пространства имен. Теперь я не вижу причин запрещать такие аргументы, тем более что их полезность очевидна. Передача шаблонов классов в качестве аргументов шаблонов одобрена на заседании комитета в Сан-Диего в марте 1994 г.

15.4. Ограничения на аргументы шаблонов

На аргументы шаблонов не накладывается ограничений. Проверка типов откладывается до момента инстанцирования шаблона [Stroustrup, 1988b]:

Стоит ли требовать от пользователя, чтобы он задавал набор операций, применимых к аргументу шаблона типа type? Например:

Для аргумента шаблона типа Т должны быть заданы операции =, ==, < и <=

template < class Т {

Т& operator={const Т&); int operator==(const Т&, const T&); int operator<=(const T&, const T&); int operator<(const T&, const T&);

>

class vector { .. .

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



1 ... 108 109 110 [ 111 ] 112 113 114 ... 144

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