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

1 ... 63 64 65 [ 66 ] 67 68 69 ... 196


Из презентации Херба Саттера (Herb Sutter).

Этот интерфейс используется некоторыми компиляторами, в том числе Comeau С++.

объявляться с префиксом std::. Однако некоторые элементы из пространства имен std остались неуточненными. Видите, какие именно?

Не указано, какие операторные функции должны использоваться в программе. Мы хотим, чтобы происходило следующее:

std;: operator ( std:: operator ( std:: cout. s). std:: endl):

Ho вводить эту конструкцию соверщенно не хочется!

Исходная команда вывода работает именно так, как мы хотим, благодаря механизму ADL. Если в программе присутствует неуточненный вызов функции, объявление которой отсутствует в обычной области видимости, то поиск подходящих объявлений функций производится в пространствах имен каждого из ее аргументов. В исходной команде первой вызывается функция

operator (std:: cout. s):

Поскольку такая функция отсутствует в области видимости исходного фрагмента, компилятор замечает, что первый аргумент функции (std::cout) принадлежит пространству имен std; он включает это пространство имен в список поиска уникальных функций, лучще всего соответствующих сигнатуре operator (std::ostream& std::string). Такое объявление находится в пространстве имен std через заголовок <string>.

Без ADL работать с пространствами имен было бы крайне неудобно. Обратите внимание: механизм ADL обычно анализирует все объявления с указанным именем из всех доступных пространств имен. При отсутствии единого оптимального совпадения возникает неоднозначность.

Чтобы запретить применение ADL, заключите имя функции в круглые скобки:

(f)(x. у): Подавление механизма ADL

Теперь рассмотрим следующую программу:

: С05:Lookup.срр

Правильно работает только в EDG и Metrowerks (со специальным ключом) #1nclude <iostream> using std::cout: using std::endl:

void f(double) { cout f(double) endl: }

tempiate<class T> class X { public: void g() { f(l): }

void f(int) { cout f(int) endl: }

int mainO {

X<int>().g(); } /:-

Из всех имеющихся у нас компиляторов программа работала правильно только в интерфейсе Edison Design Group, хотя в некоторых компиляторах (например, Metrowerks) правильное поведение при поиске активизируется специальным



Также основанный на одном из примеров Херба Саттера.

ключом. Поскольку f является независимым именем, которое может быть разрешено на ранней стадии по контексту определения шаблона, когда в области видимости находится только f(double), результат должен выглядеть так:

f(double)

К сожалению, многие существующие программы зависят от этого нестандартного поведения с привязкой вызова f(l) из д() к более позднему определению f(int), поэтому производители компиляторов не хотят вносить изменения.

Рассмотрим более подробный пример:

: C05:Lookup2.cpp {-bor}{-g++}{-dmc}

Microsoft: необходим ключ -Za (режим ANSI)

#incl ude <algorithm>

#incl ude <iostream>

#incl ude <typeinfo>

using std::cout:

using std::endl:

void go { cout global gO endl: }

template <class T> class Y { public: void gO

{ cout Y< typeid(D.nameO >::g() endl; } void hO {

cout Y< typeid(T).nameO >::h() endl:

typedef int E;

typedef double E:

tempiate<class T> void swap(T& tl. T& t2) { cout global swap endl; T temp = tl; tl - t2; t2 = temp;

tempiate<class T> class X : public Y<T> { public: E fO { gO:

this->h();

T tl - TO. t2 - T(l);

cout tl endl;

swap(tl. t2);

std::swap(tl. t2):

cout typeid(E).nameO endl:

return E(t2);

int mainO { X<int> x;

cout X.fO endl: } /:-



Результат выполнения программы будет выглядеть так:

global gO

Y<int>::h()

global swap

double

Теперь посмотрим на объявления в X::f().

Е, тип возвращаемого значения X::f(), не является зависимым именем, поэтому его поиск производится при обработке шаблона. В результате обнаруживается определение типа, в соответствии с которым Е определяется как double. На первый взгляд это выглядит странно, поскольку в нешаблонных классах сначала будет найдено определение Е в базовом классе, но таковы правила (базовый класс Y является зависимым базовым классом, поэтому в момент определения шаблона поиск в нем производиться не может).

Вызов д() тоже независим, поскольку он не содержит упоминаний Т. Если бы функция д() имела параметры, относящиеся к типу класса, определенного в другом пространстве имен, то механизм ADL начал бы работать, так как в области видимости нет определения д() с параметрами. В итоге для вызова устанавливается соответствие с глобальным объявлением д().

Вызов this->h() является уточненным; уточнение (this) соответствует текущему объекту, относящемуся к типу X, который, в свою очередь, зависит от имени Y<T> из-за наследования. В X не существует функции h(), поэтому поиск выполняется в области видимости базового класса X, то есть Y<T>. Данное имя является зависимым и потому рассматривается на стадии специализации при наличии надежной информации о У<Т> (включая все потенциальные специализации, которые могли быть написаны после определения X), поэтому в конечном счете вызывается Y<int>::h().

Объявления tl и t2 являются зависимыми.

Вызов operator (couttl) зависим, потому что tl относится к типу Т. Поиск выполняется позднее, когда Т соответствует int, а оператор для int находится в std.

Неуточненный вызов swap() зависим, потому что его аргументы относятся к типу Т. В конечном счете это приводит к специализации глобальной функции swap(int&,int&).

Уточненный вызов std::swap() не является зависимым из-за присутствия фиксированного пространства имен std. Компилятор знает, что нужное объявление нужно искать в std (чтобы уточненное имя считалось зависимым, в квалификаторе слева от парного двоеточия должен упоминаться параметр шаблона). Позднее шаблон функции std::swap() генерирует std::swap(int&,int&) на стадии специализации. Других зависимых имен в X<T>::f() нет.

Подведем итог: поиск зависимых имен осуществляется в момент специализации; исключение из этого правила составляют неуточненные зависимые имена, поиск которых начинается с определения шаблона. Поиск независимых имен в шаблонах производится рано, при обработке определения шаблона (при необхо-



1 ... 63 64 65 [ 66 ] 67 68 69 ... 196

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