2013-10-06 6 views
3

Я воспроизводству ниже аргумента-зависимого поиска (ADL) пример, приведенный на страницах 396 и 397 Страуструп книги (4-е издание):мне нужно некоторые разъяснения относительно этого примера на новой книге Страуструпа о ADL

namespace N { 
    struct S { int i; }; 
    void f(S); 
    void g(S); 
    void h(int); 
}; 

struct Base { 
    void f(N::S); 
}; 

struct D : Base { 
    void mf(N::S); 

    void g(N::S x) 
    { 
     f(x); // call Base::f() 
     mf(x); // call D::mf() 
     h(1); // error: no h(int) available 
    } 
}; 

Что приведенные выше комментарии правильны (я их протестировал), но это, похоже, не согласуется с тем, что автор говорит в следующем абзаце:

В стандарте правила для зависящего от аргумента поиска сформулированы в терминах связанных пространств имен (iso §3.4.2). В основном:

  • Если аргумент является членом класса, ассоциированные пространства имен самого (в том числе его базовые классов) класс и вмещающих пространства имен класса.
  • Если аргумент является членом пространства имен, связанные пространства имен являются охватывающими пространствами имен.
  • Если аргумент является встроенным типом, не существует связанных пространств имен.

В примере, x, который имеет тип N::S не является членом класса D, ни его основания Base. Но это член namespace N. Согласно второму этапу выше, функция N::f(S) должна быть вызвана, а не Base::f().

Результат выше, также, кажется, не согласен со второй пулей в пункте 3.4.2p2 в стандарте, в котором говорится:

Если T является типом класса (включая профсоюзы), связанные с ним классы : сам класс; класс которого он является членом, если таковой имеется; и его прямых и косвенных базовых классов. Его ассоциированные пространства имен представляют собой пространства имен , членами которых являются ассоциированные классы. Кроме того, , если T является специализацией шаблона класса, его ассоциированные пространства имен и классы также включают: пространства имен и классы, связанные с типами аргументов шаблона, предоставленными для параметров шаблона (за исключением параметров шаблона шаблона); пространства имен, членами которых являются любые аргументы шаблона шаблона ; и классы, в которых используются любые шаблоны членов , используемые в качестве аргументов шаблона шаблона.

+1

ADL срабатывает только в том случае, если функция не найдена с регулярным поиском. –

+0

@ n.m неверно. Правило заключается в том, что ADL отключен, если обычный поиск находит локальное фактическое объявление функции (например, '{void f(); ..') или функция члена класса. Все остальные обычно найденные декларации (включая объявления локального использования) все еще позволяют ADL. –

+1

@ н.м. Если это так, то в тот момент, когда вы выполнили 'operator <<' для своего класса в глобальном пространстве имен, вы больше не сможете писать 'std :: cout << std :: string (« Hello »);'. Этого, конечно, не бывает. –

ответ

4

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

  • декларацию члена класса или
  • объявление функции блока-сферы, которая не является использованием декларация, или
  • декларацию, которая не является ни функции или функции шаблона

тогда Y пуст. В противном случае ...

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

+0

Я приму свой ответ. Но я до сих пор не понимаю пример в 3.4.2p3: 'g (parm, 1)', 1 - это int, а не float! – Belloc

+0

Существует локальное (block-scope) объявление 'extern void g (NS :: T, float);' in 'main'. Это подавляет ADL, в секунду, указанную выше. –