Д. Вандевурд, Н.М. Джосаттис - Шаблоны C++. Справочник разработчика (2003) (1160769), страница 26
Текст из файла (страница 26)
9.1. Систематизация имен Имена в С++ классифицируются разными способами, причем этих способов существует огромное количество. Чтобы помочь справиться с этим изобилием терминологии, все способы классификации имен сведены в табл. 9.1.
К счастью, многие вопросы, касающиеся шаблонов С++, стануг гораздо понятнее, если ознакомиться с основными концепциями именования. 1 Имя является полным (квалифицированным) именем (срмйбеб паню), если область видимости, которой оно принадлежит, явно указывается либо с помощью оператора разрешения области видимости (:: ), либо с помощью оператора доступа к членам класса (. или ->) Например, савв->сорпа — полное имя, а осипе — нет (даже если само по себе соипс в действительности является ссылкой на член класса). Глава 9. Имена в шаблонах Таблица 9.1.
Систематизация имен Классификация Пояснении и примечания Имя, которое содержит только неразрывные последовательности букв, знаков подчеркивания ( ) и цифр. Идентификатор не может начинаться с цифры; кроме того, некоторые идентификаторы зарезервированы в реализации языка: их нельзя самостоятельно вводить в программы (используйте простое правило: избегайте идентификаторов, начинающихся с подчеркиваний и двойных подчеркиваний).
Понятие "буква" интерпретирусгся расширенно: сюда включаются специальные универсальные имена символов (ип(гвгва! сяагасгвг пател — УС]т), с помощью которых кодируются знаки из неалфавитных языков Ключевое слово орегасог, за которым следует символ, обозначающий оператор, например орегасог пеы или орегасог(]. Многие операторы имеют аяьтернативные представления. Например, орегагог ь можно записать как орегасог Ьйсапс], даже если он обозначает унарный оператор получения адреса Используется для обозначения определенного пользователем неявного оператора преобразования, например орегасог Тпсй, который можеттакже быль представлен как орегасог Тпг Ьй санс] Имя шаблона, за которым следуют аргументы шаблона, заключенные в угловые скобки, например Г Твг<Т, Тпк, о>.
(Строго говоря, для имени идентификатора шаблона стандартом С++ разрешены только простые идентификаторы. Однако зто, возможно, недосмотр: должен быть разрешен также идентификатор функции опеРатоРа, т.е. орегагог+<х< 1пс») Обобщение идентификатора. Неполный идентификатор может быль любым нз приведенных выше видов идентификаторов (идентификатор„идентификатор функции оператора, идентификатор функции преобразования типа нли идентификатор шаблона), а также "имя деструктора" (например, записи типа -цаса илн -Ьйяг<Т,Т,Ь]>) Полное имя, которое включает имя класса или пространства имен либо оператор разрешения глобальной области видимости. Заметим, что такое имя может быть полным само по себе. Примеры: ::х, Я::х, Аггау<Т>::уи::Ы::А<Т>:: х.
Идентификатор Идентификатор функции оператора Идентификатор функции преобра- зования типа Идентификатор шаблона Неполный (ппцпайбег]) иден- тификатор Полный (цнайГ1ео) идентификатор ! 2. Имя является зависимым именем, если оно каким-либо образом зависит от пара' метра шаблона. Например, вес]:: згесгог<Т>:: ьгегагог — зависимое имя, если Т вЂ” параметр шаблона, и независимое, если Т является известным значением, заданным с помощью конструкции гурес]ей (например, Тпс). 9.2.
Поиск имен 145 Окончание табл. 9.) Классификация Пояснения н примечания Этот термин в стандарте не определен, но мы используем его для обозначения имен, которые подвергаются так называемому полному (нвалифииированному) поисну. В частности, зто могут быть полные или неполные идентификаторы, которые используются после уточнения с помощью явного оператора доступа (. или ->). Примеры: Я::х, гМв->й и р->А::аь Однако просто с1авв мев в контексте, когда он неявно эквивалентен кЬзв->с1аяя аевь не является полным именем: доступ к члену класса должен быль явным Неполный идентификатор, который не является полным именем.
Это нестандартный термин, но он соответствует именам, которые подвергаются тому, что в стандарте именуется неполным (индиа(феа) поиском Полное или неполное имя Полное имя Неполное имя Имя, которое каким-либо образом зависит от параметра шаблона. Очевидно, что любое полное или неполное имя, которое явно содержит параметр шаблона, является зависимым. Более того, полное имя, которое включает оператор доступа к члену класса (.
или - ), является зависимым, если тип выражения в левой части оператора доступа зависит от параметра шаблона. В частности, Ь в сЬзв->Ь является зависимым именем, когда оно присутствует в шаблоне. И наконец„ идентификатор йс(епс в вызове вида депп (х, у, я) является зависимым именем тогда и только тогда, когда любое из выражений аргументов имеет тип, который зависит от плрамегра шаблона Имя, которое не является зависимым согласно данному выше оп- ределению Зависимое имя Независимое имя С этой таблицей полезно познакомиться хотя бы для того, чтобы получить некоторое пРедставление о терминах, которые иногда используются при описании тем, касающихся шаблонов С++. Однако запоминать точное значение каждого термина вовсе не обязательно.
Если возникнет необходимость, всегда можно вернуться к данной таблице. 9.2. Поиск имен Существует много незначительных деталей, касающихся поиска имен в С++, но здесь мы остановимся только на нескольких основных концепциях. Подробностям будем уделять внимание только в случаях, когда нужно убедиться в правильности интуитивной трактовки, и в "патологических" случаях, которые, тем не менее, описаны в стандарте. Поиск полных имен проводится в области видимости, вытекаюшей из уточняюшей конструкции.
Если эта область видимости является классом, то поиск также проводится н в базовых классах. Однако при поиске полных имен не рассматриваются области ви- Глава 9. Имена в шаблона ) 146 димости, охватывающие данную. Основной принцип такого поиска иллюстрируется при.
веденным ниже кодом. Ьпс х) с1авв В ( ри)э11с: 1пг 1; с1авн В: ри)з11с В ( )' // Будет найдено В::1 // ОШИБКА: ::х из охватывающей // области видимости найдено не будет Поиск же неполных имен, напротив, выполняется в последовательно расширяющихся областях видимости, охватывающих данную (однако в определениях функций-членов сначала проводится поиск в области видимости класса и его базовых классов, а уже затем в охватывающих областях видимости). Такая разновидность поиска называется обычным поиском (оп(ашгу!оо)гнр). Приведенный ниже пример иллюстрирует главную идею, лежащую в основе обычного поиска.
ехгегп 1пг соиле // (1) // (2) 1пс 1оо)сир ехазлр1е(йпг соиле) ( Ы (соиле < 0) ( 1пг соила = 1; 1оо)сир ехащр1е(соиле)г // (3) // Неполное имя соила // ссылается на (3) гесигп соиле + ::соиле> Современные методы поиска неполных имен в дополнение к обычному поиску могут включать так называемый поиск, зависящий от аргументов (аунтепг-г)ерепг)епг (аойлр — АРЬ) .
Прежде чем перейти к подробному рассмотрению А()Ь, рассмотрим механизм этого поиска на примере шаблона пах ( ) . 1 Этот поиск также называется поиском Каннга (нлн расширенным поиском Клинга) в честь Эндрю кеннга (Алогсзг Косо)в). который впервые предложил вариант данного механизма чойс) Е(В* рс() ( рб->1 = 3; В::х = 2; // Первое, неполное соиле // ссылается на (2) // Второе, полное соиле // ссылается на (1) 9.2. Поиск имен 147 Севр1асе <Гурепаве Т> Тп11пе т сопвгй вах(Т сопвсй а, т сопвсй Ь) ( гехцгп а < Ь ? Ь: а; Предположим, чю нам необходимо прнмениь этот шаблон к типу, определенному в другом про. стрянстае имен. павеврасе ВйдиаГЬ ( с1авв В1дИцвЬег ( Ьоо1 орегасог < (В1дмпвьег сопвгй, ВйдипвЬег сопвтй) з пвйпд ВйдМаГЬ::ВгдипвЬег; нойс) д(ВТдипвЬег соплей а, В1дИпвЬег соплей Ь) ВйдипвЬег х = вах(а,Ь)з Проблема заключается в том, что шаблону вах () ничего не известно о пространстве имен ВйдМаСЬ и с помощью обычного поиска не будет найден оператор <, применимый к значениям типа ВздИпвЬег.
Если не ввести некоторые специальные правила, такие ситуации в значительной степени сокращают применимость шаблонов в контексте пространств имен С++. Поиск АО). является отвесом С++ на необходимость введения таких специальных правил. 9.2.1. Поиск, зависящий от аргументов А1И. применяется только к неполным именам, которые выглядят наподобие имени функции, не являющейся членом, в вызове функции. Если при обычном поиске будет найдено имя функции-члена или имя типа, то А1Х.
не применяется. АП). также запрещен, если имя функции, которая должна быть вызвана, заключено в круглые скобки. В противном случае, если после имени следует заключенный в круглые скобки список выражений аргументов, АШ. выполняется путем поиска имени в пространствах имен и классах, "ассоциированных" с 'типами аргументов вызова. Точное определение этих ассоциированных пространств имен и ассоииированных классов будет дано позже, но интуитивно их можно определять как все пространства имен и классы, которые очевидным образом непосрелственно связаны с данным типом. Например, если тип является указателем на класс Х, то ассоциированные классы и пространство имен будут включать Х, а также все простРанства имен и классы, к которым принадлежит Х.
148 Глава 9. Имена в шаблонах ' Точное определение множества ассоциированных пространств имен и ассоциированных каласов для данного типа регламентируется приведенными ниже правилами. ° Для встроенных типов это пустое множество. я Для указателей и массивов множество ассоциированных пространств имен и классов — это пространства имен и классы типа, на который указывает указатель или который является типом элемента массива. ° Для перечислимых типов ассоциированным пространством имен является пространство имен, в котором обьявлено перечисление. Для членов классов ассоциированным классом является включающий их класс.
° Для классов (включая объединения) множеством ассоциированных классов является сам тип класса, включающий его класс, а также все непосредственные или опосредованные базовые классы. Множество ассоциированных пространств имен — зто пространства имен, в которых объявлены ассоциированные классы. Если класс является инстанцированным экземпляром шаблона, то сюда включаются также типы аргументов типа шаблона, а также классы и пространства имен, в которых объявлены шаблонные аргументы шаблона. ° Для функций множества ассоциированных пространств имен и классов включают пространства имен и классы, ассоциированные со всеми типами параметров, а также ассоциированные с типами возвращаемых значений.