Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003) (1160769), страница 57
Текст из файла (страница 57)
Классы свойств и стратегий 308 // Перемещение п элементов в и других аввегс(вгс != с)вс) 1 хог(в1ке С К = Оз К < пз ++К) ( с)вс [К] = вгс [К]; вгс [К] ° Т () 1 вгаг1с чсЫ моче 1п1г(Т* вгс, чо1с)* с)вс) ( // Перемещение элемента // з неинициализированную память азвегс(вгс 1= с[вс) 1 ::пеи(с(вг) Т(*вгс); вгс->-Т() 1 вгзг1с чо1с) щоче 1п1Г п(Т сопвс* вгс, чо1с)* с)вс, в1ге Г и) ( // Перемещение и элементов // в неинициализированную память ввзегс(вгс 1= с(вг) 1 бог(вйзе Г К = О; К < и; ++К) ( ::пеи((чоЫ*) ((с)твг*)с)вс + )с) ) Т(вгс[1с] ) 1 вгс [К] .
-Т () 1 ) ) Здесь термин перемещение означает, что значение перенесено из одного места в другое и больше первоначального значения не существует [или, если точнее, первоначальное расположение может быть уничтожено). С другой стороны, операция копирования гарантирует, что и источник, и целевой обьект содержат корректные идентичные значения.
Не следует путать это с различием между функциями щещсру () и щещщоче (), которые существуют в стандартной библиотеке С: в этом случае функция щещпюче () считает, что исходная и целевая области памяти могут перекрываться, а функция щещсру () строится в предположении, что это невозможно. В нашей реааизации свойств СВМ всегда предполагается, что исходная и целевая области памяти не перекрываются. В про мышленную библиотеку, вероятно, следует добавить операцию сдвига, которая первые щает объекты в пределах непрерывной области памяти. Ради простоты изложения она здесь не рассматривается.
Все функции-члены нашего шаблона свойств стратегий являются статическими. Зто справедливо почти всегда, поскольку функции-члены предназначены для применен®' к объектам с типом параметров, а не к объектам с типом классов свойств.
другая частичная специализация реализует свойства для типов, которые могут ко"и роваться побайтово. 15.3. Свойства стратегий ЗОЯ // сга1св/свщ2.)трр ()1пс1цйе <сзгг1пд> ()1пс1цйе <саввегс> й?пс1цйе <всййе1.)з> ййпс1цйе "сзщ1.)трр" // Частичная специализация для быстрого // побайтового копирования объектов Сещр1аее <Гурепаще Т> с1авз В1гбгС1авзСЯМ<Т,Ггце> рц)з11с В1сОгС1аввСЯМ<Т,йа1ве> ( рц)з11с: вгагйс чо?й сору п(т сопвс* вгс, т* йвс, в1яе г п) ( // Копирование и элементов в п других элементов всй::щетсру( (чоЫ*) йвс, (чоЫ*) вгс, п»в1гео1(Т) ); всаг1с чоЫ сору 1п?С п(Т сопит» вгс, чоЫ* йвг, вйяе С и) ( // Копирование п элементов // в неинициализированную память зсй: гщещсру(йве, (чоЫ*]вгс, п»з1аео1(Т)); всасйс чо1й пюче п(Т* вгс, Т* йвс, в1ге Г и) ( // Перемещение и элементов в и других элементов авзегс(вгс != йвс); вгй::щетсру((гойй»)йвс, (чоЫ*)вгс, п*вйкеоб(Т)) всаг1с чо1й моче 1п1Г п(Т сопвс» вгс, чо1й» йзс, в1ае с и) ( // Перемещение и элементов // в неинициализированную память азвегг (вгс != йвс)? всй::тещсру(йвг, (чо1й*)вгс, п»в1аеой!Т)); Здесь использован дополнительный уровень наследования для того, чтобы упростить реализацию свойств для типов, которые могут копироваться побайтоао.
Конечно, зто не единственная возможная реализация; на самом деле для определенных платформ непло"им решением может оказаться использование встроенного ассемблера (например, чтобы воспользоваться аппаратными операциями обмена). Глава 15. Классы свойств и стратегий 310 15.4. Заключение Натан Майерс (Хайзап Муегз) был первым, кто формализовал концепцию параметров- свойств. Первоначально он представил их в Комитет по стандартизации С++ в качестве средства, определяющего, каким образом символьные типы данных должны обрабатываться в компонентах стащартных библиотек (например, во входных и выходных потоках).
В то время он называл нх багажными шаблонами (Ъайяайе (ешр!а(ез) и отмечал, Что они содержат свойства. Однако некоторым членам комнтеш не нравился термин багаж, и вместо зтого был поддержан термин свойства (Пайз), который широко используется в настоящее время. Обычно пользователь вообще не имеет дела со свойствами: заданные по умолчанию классы свойств удовлетворяют распространенным потребностям, а поскольку они заданы по умолчанию, то вообще не появляются в исходном тексте пользователя. Это соображение является дополнительным доводом в пользу длинных описательных имен для заданных по умолчанию шаблонов свойств. Если же пользовательский код адаптирует поведение шаблона, предоставляя пользовательский аргумент свойств, то всегда можно использовать определение синонима типа с помощью конструкции гурес)ей.
В нашем рассмотрении шаблоны свойств представляли собой исключительно шаблоны классов. Строго говоря, это не обязательно. Если требуется только одно свойство стратегии, оно может быть обычным шаблоном функции, например: Гевр1асе <Гурепазае Т, чоЫ (*Ро11су)(Т сопвгй, Т сопвсй)> с1авв х; Однако первоначальная цель свойств состоит в уменьшении количества вторичных параметров шаблона, чего нельзя достичь, инкапсулируя в параметре шаблона только одно свойство (отсюда, в частности, становится понятно, почему Майерс предлагал определять термином багаж упакованную коллекцию свойств).
Мы еще вернемся к данному вопросу в главе 22, "Объекты-функции и обратные вызовы". Стандартная библиотека определяет шаблон класса вгб:: с)заг сгайсв, который используется в качестве параметра свойств стратегии. Чтобы упросппь адаптацию алгоритмов для работы с итераторами ЗТ1., предусмотрен очень простой шаблон свойств вЫ:: йсегасог ггайгв (используемый в интерфейсах стандартных библиотек). Еше один шаблон свойств стандартной библиотеки — вас)::пшаегйс 11юйгв. Шаблоны классов вгб г: ипату Еппсг1оп и всс1:: Ыпагу Еппсгйоп попадают в зту же категорию и являются очень простыми функциями типа: они просто определяют имена-члены для типов своих аргументов с помощью конструкции сурес)ей.
Наконец, распределение памяти для стандартных типов контейнеров обрабатывается с использованием классов свойств стратегий. Стандартным шаблоном для зтого является ясй:: а11осагог. Классы стратегий разрабатывались многими программистами. Особо большой вклад в эту область внес Андрей Александреску (Апбге( А)ехапбгезсп), благодаря которому термин класси страиегий получил такое широкое распространение, а его яки~у Моавги С++ Вел(яи (Ц можно считать наиболее полной работой по данной теме, безусловно, гораздо полнее, чем зта глава.
Глава 1б Шаблоны и наследование Нет никакого повода считать, что шаблоны и наследование взаимодействуют каким-то особым образом. Следует отметить лишь тот факт (см. главу 9, "Имена в шаблонах"), что порождение от зависимых базовых классов требует особой тщательности при использовании неполных имен. Однако некоторые технологии программирования применяют так называемое параметризованное наследование, которое рассматривается в этой главе.
16.1. Именованные аргументы шаблона Зачастую различные методы работы с шаблонами приводят к тому, что шаблон содержит весьма значительное число параметров. Конечно, как правило, многие из них имеют вполне приемлемые значения по умолчанию. Естественный способ определения такого шаблона класса может выглхлеть, как показано ниже. Ро11су1 Ро11су2 Ро11суЗ Ро11су4 = Вебац1сРо11су1, = Вебац1СРо11су2, = Вебац1СРо1зсуЗ, = Вебац1СРо11су4> сешр1аке<гурепаше кур епаше турепаше тур епаше с1авв Втеас)Я11сег 1 Обратите внимание, что подобное расширение юыкя дпя аргументов вызова функции было предложено (и отклонено) в процессе стандартизации языка С++ еше раньше (более подробно зто рассматривается и разлеяе 13.9, стр. 242).
Вероятно, такой шаблон чаще всего будет использоваться с аргументами по умолчанию, с применением синтаксиса Втеас)я11сег<>. Однако, если некоторый аргумент имеет значение не по умолчанию, все предшествующие ему аргументы должны быть явно указаны (даже если они используют значения по умолчанию). Понятно, что было бы гораздо лучше использовать конструкцию Втеас)Я11сег <Ро11суЗ = сцнсош>, чем стандартную, имеющую вид Вгеас)я11сет<з)ебац1сРо11су1, ))ебац1СРо11су2, Сцвсош>. Далее рассматривается метод, дающий возможность использовать синтаксис, очень похожий на описанный .
Глава 16. Шаблоны и наследование З)г Наш метод заключается в размещении значений типа по умолчанию в базовом классе и в переопределении некоторых из них в процессе наследования. Вместо непосредственного ука- зания аргументов типа определим их через вспомогательные классы. Например, можно напи- сать Вгеас)Я11сег<Ро11суЗ 1в<Сивсощ». Поскольку каждый аргумент шаблона мо- жет описывать любую стратегию, значения по умолчанию не могут быль различными. Иными словами, на верхнем уровне все параметры шаблона эквивалентны.
Сещр1аге <куренное Ро11суЯеггег1 = Вегац1СРо11суАгдв, Сурепаще Ро11суЯеггег2 = Вейаи1СРо11суАгдв, Сурепаще Ро11суЯеггегЗ = Вебаи1ГРо11суАгдв, сурепаще Ро11суЯессег4 = Вейаи1сРо11суАгдв> с1авв Вгеас)Я11сег ( Суребеб Ро11суЯе1есгог<Ро11суЯеггег1, Ро11суЯеггег2, Ро11суЯеггегЗ, Ро11суЯеггег4> Ро11сйев; // Использование Ро11сйев:: Р1, Ро11сйев:: Р2, // для обращения к различным стратегиям После этого остается только одна проблема — написать шаблон Ро11суЯе1ессог.