Черновик ISO C++ — 3.4.2/3 — Поиск имени, зависящего от аргумента

Пункт из черновика ISO C++ (n3290):

3.4.2/3 Поиск имени, зависящего от аргумента:

Пусть X будет набором поиска, созданным неквалифицированным поиском (3.4.1), и пусть Y будет набором поиска, созданным поиском, зависящим от аргумента (определяется следующим образом). Если X содержит

  • объявление члена класса (#1) или
  • объявление функции блочной области, которое не является объявлением использования (# 2) или
  • объявление, которое не является ни функцией, ни шаблоном функции (#3)

тогда Y пусто. В противном случае Y — это набор объявлений, найденных в пространствах имен, связанных с типами аргументов, как описано ниже. Набор объявлений, найденный при поиске имени, представляет собой объединение X и Y.

Есть ли пример фрагмента кода, демонстрирующий ADL с участием № 1, № 2 и № 3?


person user751747    schedule 03.08.2011    source источник


Ответы (3)


Я думаю, что этот код охватывает все случаи (также доступен на http://ideone.com/CbyJv). Если вы не выберете C++0x в ideone, то разрешен вариант №2 (но gcc 4.5.2 его улавливает).

#include <iostream>

// ::f
void f (int i) { std::cout << "::f\n" ; }

// Simple case
void OK1() {
  f (99) ; // Calls ::f
}

// Argument-dependend lookup
namespace MyNamespace {
struct S { int i ; } ;
void f (S& s) { std::cout << "MyNamespace::f\n" ; }
}

void OK2() {
  MyNamespace::S s ;
  f (99) ;   // Calls ::f
  f (s) ;    // Calls MyNamespace::f because the type of s is declared in MyNamespace
}

// Declaration of a class member (#1)
struct C {
  static void ERROR1() {
    MyNamespace::S s ;
    f (s) ;        // Error: MyNamespace::f not matched, because Y is empty (#1)
  }
  static void f() { // Declaration of a class member (#1)
    std::cout << "C::f\n" ;
  }
} ;

// Block-scope function declaration (#2)
void ERROR2() {
  void f() ; // Block-scope function declaration (#2)
  MyNamespace::S s ;
  f (s) ;    // Error: MyNamespace::f not matched, because Y is empty (#2)
}

// Declaration that is neither a function or a function template (#3)
void ERROR3() {
  MyNamespace::S s ;
  f (s) ;            // OK: MyNamespace::f called
  typedef int f[3] ; // Declaration that is neither a function or a function template (#3)
  f (s) ;            // Error: MyNamespace::f not matched, because Y is empty (#3). This is an initialiser
}
person TonyK    schedule 03.08.2011

Номер 1 довольно прост — если вы ищете имя N внутри класса, а в классе есть член N, вот и все! Вам не нужно искать где-либо еще.

Номер 2, я думаю, похож, но внутри блока

{
    void f(double);

    f(42);
}

код попытается вызвать объявленную там функцию f, если это возможно, и сдастся в противном случае.

Номер 3 снова аналогичен. Если вы ищете имя N и находите что-то с этим именем, не являющееся функцией, вам не нужно искать перегрузки.

person Bo Persson    schedule 03.08.2011

Для чего это стоит, это также называется поиском Кенига. У меня нет под рукой примеров для всех трех, но Бо Перссон уже предоставил некоторые из них.

person WaffleSouffle    schedule 03.08.2011