Читаем Thinking In C++. Volume 2: Practical Programming полностью

void f(int) { cout << "f(int)\n"; }

int main() {

  X().g();

}

The only compiler we have that gets this correct right out of the box is the Edison Design Group front end. (A number of compilers use this front end, including Comeau C++.) The output should be:.

f(double)

because f is a non-dependent name that can be resolved early by looking in the context where the template is defined, when only f(double) is in scope. Unfortunately, there is a lot of code in existence that depends on the non-standard behavior of binding the call to f(1) inside g( ) to the latter f(int), so compiler writers have been reluctant to make the change. (Some compilers, such as the Metrowerks compiler, have an option to enable the correct lookup behavior.).

Here is a more detailed example, also based on an example from Herb Sutter:

//: C05:Lookup2.cpp

//{-bor}

//{-g++}

// Microsoft: use option –Za (ANSI mode)

#include

#include

using std::cout;

using std::endl;

void g() { cout << "global g()\n"; }

template

class Y {

public:

  void g() { cout << "Y<" << typeid(T).name()

   << ">::g()\n"; }

  void h() { cout << "Y<" << typeid(T).name()

   << ">::h()\n"; }

  typedef int E;

};

typedef double E;

template

void swap(T& t1, T& t2) {

  cout << "global swap\n";

  T temp = t1;

  t1 = t2;

  t2 = temp;

}

template

class X : public Y {

public:

  E f() {

    g();

    this->h();

    T t1 = T(), t2 = T(1);

    cout << t1 << endl;

    swap(t1, t2);

    std::swap(t1, t2);

    cout << typeid(E).name() << endl;

    return E(t2);

  }

};

int main() {

  X x;

  cout << x.f() << endl;

} ///:~

The output from this program should be:

global g()

Y::h()

0

global swap

double

1

Looking at the declarations inside of X::f( ), we observe the following:

·         The return type of X::f( ), which is E, is not a dependent name, so it is looked up when the template is parsed, and the typedef naming E as a double is found. This may seem strange, since with non-template classes the declaration of E in the base class would be found first, but those are the rules. (The base class, Y, is a dependent base class, so it can’t be searched at template definition time).

·         The call to g( ) is also non-dependent, since there is no mention of T. If g had parameters that were of class type of defined in another namespace, ADL would take over, since there is no g with parameters in scope. As it is, this call matches the global declaration of g( ).

·         The call this->h( ) is a qualified name, and the object that qualifies it (this) refers to the current object, which is of type X, which in turn depends on the name Y by inheritance. There is no function h( ) inside of X, so lookup will naturally want to search the scope of X’s base class, Y. Since this is a dependent name, it is looked up at instantiation time, when Y can be reliably known (including any potential specializations that might have been written after the definition of X); so it calls Y::h( ).

·         The declarations of t1 and t2 are dependent, of course.

·         The call to operator<<(cout, t1) is dependent, since t1 is of type T. This is looked up later when T is int, and the inserter for int is found in std.

·         The unqualified call to swap( ) is dependent because its arguments are of type T. This ultimately causes a global swap(int&, int&) to be instantiated, of course.

·         The qualified call to std::swap( ) is not dependent, because std is a fixed namespace; so the compiler knows to look there for the proper declaration. (The qualifier on the left of the "::" must mention a template parameter for a qualified name to be considered dependent.) The std::swap( ) function template later generates std::swap(int&, int&), at instantiation time. No more dependent names remain in X::f( ).

To clarify and summarize: name lookup is done at the point of instantiation if the name is dependent, except that for unqualified dependent names the normal name lookup is also attempted early, at the point of definition. All non-dependent names in templates are looked up early, at the time the template definition is parsed. (If necessary, another lookup occurs at instantiation time, when the type of the actual argument is known.).

(Whew!) If you have studied this example to the point that you understand it, prepare yourself for yet another surprise in the next section when friend declarations enter the picture.

<p>Templates and friends</p>
Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных