|
Программирование >> Разработка устойчивых систем
void pop back() { if(count > 0) -count: T* beginO { return data; } T* endO { return data + count: } tempiate<class T,size t N,template<class.size t> class Seq> class Container ( Seq<T.N> seq: public: void append(const T& t) ( seq.push back(t): } T* beginO { return seq.beginO: } T* endO { return seq.endO: } int mainO ( const size t N = 10: Centalner<int. N. Array> container: theData.append(l): theData.append(2); int* p = container.beginO: whne(p != container.endO) cout *p++ endl: } III:- И снова при объявлении Seq в объявлении Container имена параметров не обязательны, но переменная seq должна объявляться с двумя параметрами, чем и объясняется появление нетипового параметра N на верхнем уровне. Использование аргументов по умолчанию совместно с шаблонами в качестве параметров шаблонов создает определенные проблемы. Когда компилятор анализирует внутренние параметры шаблонов, являющихся параметрами шаблонов, он не рассматривает аргументы по умолчанию, поэтому вам придется повторно перечислить значения по умолчанию для обеспечения точного совпадения. Следую-Шй пример, в котором используется аргумент по умолчанию для шаблона Array с фиксированным размером, показывает, как решается проблема с этой странностью языка: : C05:TempTemp3.cpp (-bor}{-msc} Использование шаблонов как параметров шаблонов совместно с аргументами по умолчанию #include <cstddef> #include <iostream> using namespace std: tempiate<class T. size t N = 10> Аргумент no умолчанию class Array ( T dataCNj: size t count: public: ArrayO { count = 0: } void push back(const T& t) ( if(count < N) data[count++] = t: void pop back() ( ifCcount > 0) --count: T* beginO { return data: } T* endО { return data + count: } tempiate<class T. tempiate<c1ass. size t = 10> class Seq> class Container { Seq<T> seq: Используется значение по умолчанию public: void append(const T& t) { seq.push back(t): } T* beginO { return seq.beginO: } T* endO ( return seq.endO: } int mainO { Container<int. Array> container: container.append(l): container.append(2): int* p = container.beginO: whi1e(p != container.endO) cout *p++ endl; } III:- Значение no умолчанию 10 должно присутствовать в следующей строке: tempiate<c1ass Т. tempiate<c1ass. size t = 10> class Seq> Это значение требуется как в определении seq в Container, так и в определении контейнера в main(). Единственный способ использования значения, отличного от значения по умолчанию, был показан в примере TempTempZ.cpp. Это единственное исключение из правила, гласящего, что аргументы по умолчанию должны лишь один раз указываться в единице трансляции. Поскольку стандартные последовательные контейнеры vector, list и deque (подробнее см. в главе 7) содержат аргумент-распределитель со значением по умолчанию, показанная методика пригодится, если вам когда-нибудь потребуется передать один из этих последовательных контейнеров в качестве параметра шаблона. В следующей программе контейнеры vector и list передаются двум экземплярам шаблона Container: : C05:TempTemp4.cpp {-Ьог}{-msc} Передача стандартных последовательных контейнеров в аргументах шаблонов #include <iostream> #include <1ist> #1ncl ude <memory> Объявление a11ocator<T> #include <vector> using namespace std; tempiate<c1ass T. tempiate<c1ass U. class = a11ocator<U> > class Seq> class Container { Seq<T> seq: Неявное применение a11ocator<T> public: void push back(const T& t) { seq.push back(t); } typename Seq<T>::iterator beginO { return seq.beginO; } typename Seq<T>::iterator endO { return seq.endO: } int mainO { Передача контейнера vector Container<int. vector> vContainer: vConta i ner.push back(1): vConta i ner.push back(2): for(vector<int>::iterator p = vContainer.beginO: p != vContainer.endO: ++p) { cout *p endl: Передача контейнера list Container<int. list> 1 Container: lContainer.push back(3): lContainer.push back(4): fordist<int>::iterator p2 = 1 Container.begin(): p2 != IContainer.endO: ++p2) { cout *p2 endl: } III:- Мы присваиваем имя U первому параметру внутреннего шаблона Seq, поскольку распределители стандартных последовательных контейнеров должны быть параметризованы по тому же типу, что и объекты, хранящиеся в последовательном контейнере. Кроме того, так как об использовании параметра allocator по умолчанию уже известно, мы можем исключить его из последующих ссылок на Seq<T>, как в предыдущей версии. Однако для полного понимания этого примера необходимо подробнее объяснить семантику ключевого слова typename. Ключевое слово typename Рассмотрим следующий фрагмент: : C05:TypenamedID.cpp {-Ьог} typename в качестве префикса вложенных типов tempiate<class Т> class X { Без typename в программе произойдет ошибка: typename Т::id i: public: void fO { i.gO: } class Y { public: class id { public: void gO {} int mainO { X<Y> xy: xy.fO: } /:-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |