Гарантируют ли пользовательские итераторы контейнеров ADL для рассмотрения пространства имен std? - PullRequest
7 голосов
/ 24 июля 2011

Я не собираюсь использовать это в реальном коде.Я обещаю.

Гарантирует ли стандарт, что пространство имен std будет найдено, когда аргумент функции имеет тип container::iterator, а container::iterator не является typedef для встроенного типа?

Например,

#include <set>
#include <algorithm>
int main()
{
   std::set<int> s;
   find(s.begin(), s.end(), 0); //do I have a guarantee that std::find will be found?
}

Другими словами, может ли класс итератора быть определен в таком пространстве имен, что std не будет рассматриваться ADL?

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 24 июля 2011

Я полагаю, что ответ нет в самом общем случае, но да для большинства практических реализаций.

В соответствии со стандартом ISO C ++, раздел 3.4.2 / 2, существует понятие «связанного пространства имен» для аргумента, которое определяется таким образом, что включает в себя

Если T является типом класса (включая объединения), его ассоциированными классами являются: сам класс; класс которого это член, если есть ; и его прямые и косвенные базовые классы. Связанные пространства имен являются пространствами имен в котором определены связанные с ним классы.

Это говорит о том, что если тип итератора действительно является вложенным типом внутри некоторого контейнера, например std::set, то ассоциированное пространство имен для этого итератора при вызове find будет std, поскольку std::set является связанный класс и std - это пространство имен, содержащее set. Стандарт тогда говорит, что (& sect; 3.4.2 / 2a)

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

Это будет означать, что вы действительно найдете функцию find в namespace std.

Тем не менее, не гарантированно будет работать в целом. Из спецификации (& 3.4;) мы также получаем, что

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

Итак, как вы упомянули в своем вопросе, если тип итератора имеет вид typedef, это не гарантирует правильной работы. Но, за исключением этого, кажется, что если вы знаете, что тип не является typedef, он должен быть в namespace std или вложен в класс в namespace std и должен быть выбран для ADL. Но не делай этого! : -)

5 голосов
/ 24 июля 2011

Точный тип ::iterator и т. Д. Для стандартных контейнеров определяется реализацией , поэтому в теории ничто не мешает ему быть typedef чем-то за пределами std:: (например,простой указатель).

В стандарте я не могу найти ничего другого, что предполагает, что ADL всегда будет работать в этом случае, поэтому - если кто-то не исправит меня - я должен сказать, чтоОтвет: нет, вы не можете предполагать, что find будет найдено через ADL.

...