Я воспроизвожу ниже пример аргумент-зависимого поиска (ADL), приведенный на страницах 396 и 397 книги Страуструпа (4-е издание):
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 — специализация шаблона класса, связанные с ним пространства имен и
классы также включают: пространства имен и классы, связанные с
типы аргументов шаблона, предоставляемые для параметров типа шаблона
(исключая параметры шаблона шаблона); пространства имен которых любой
аргументы шаблона являются членами; и классы которых любые
шаблоны-члены, используемые в качестве аргументов шаблона-шаблона, являются членами.
3.4.2 / 3 Позволять
X
быть набором поиска, созданным неквалифицированным поиском (3.4.1), и пустьY
быть набором поиска, созданным зависимым от аргумента
поиск (определяется следующим образом). ЕслиX
содержит
- объявление члена класса или
- объявление функции блока области видимости, которое не является объявлением использования, или
- объявление, которое не является ни функцией, ни шаблоном функции
тогда Y пуст. Иначе…
Таким образом, по сути, ADL не срабатывает, когда обычный поиск находит функцию-член или объявление локальной (блочной области) функции (или что-то, что не является функцией). Он срабатывает, когда обычный поиск находит автономную функцию пространства имен или вообще ничего не находит.
Других решений пока нет …