自定义容器迭代器是否保证ADL考虑命名空间std?

时间:2011-07-23 21:55:38

标签: c++ stl iterator std argument-dependent-lookup

我无意在实际代码中使用它。我承诺。

当函数参数的类型为stdcontainer::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?
}

换句话说,是否可以在这样的命名空间中定义迭代器类,以便ADL不会考虑std

提前致谢。

2 个答案:

答案 0 :(得分:5)

标准容器的::iterator等的确切类型是实现定义的,所以理论上没有什么可以阻止它成为typedef之外的std:: {1}}(例如普通指针)。

我在标准中找不到其他任何暗示ADL在这种情况下会一直工作的东西,所以 - 除非有人纠正我 - 我将不得不说答案是:不,你可以假设将通过ADL找到find

答案 1 :(得分:5)

我认为在最常见的情况下,答案是,但对于大多数实际实施,

根据C ++ ISO标准§3.4.2/ 2,对于参数有一个“关联命名空间”的概念,其定义方式包括

  

如果T是类类型(包括联合),则其关联的类是:类本身; 它所属的类   会员,如果有的话;及其直接和间接基类。 其关联的命名空间是命名空间   其中定义了相关的类。

这表明如果迭代器类型实际上是某个容器(如std::set)内的嵌套类型,那么调用find时该迭代器的关联命名空间将为std,由于std::set是关联类,std是包含set的命名空间。然后标准说(§3.4.2/ 2a)

  

如果名称的普通非限定查找找到类成员函数的声明,则不考虑关联的名称空间和类。否则通过查找函数名称找到的声明集是使用普通非限定查找和集合找到的声明集的并集   在与名称类型相关联的名称空间和类中找到的声明

这意味着您确实会在find中找到namespace std函数。

但是, 保证一般不会起作用。我们也从规范(§3.4.2)中得到了

  

用于指定类型的Typedef名称和using-declarations对此集合没有贡献。

因此,正如您在问题中提到的,如果迭代器类型是某种typedef,则无法保证正常工作。但是除此之外,如果您知道该类型不是typedef,它似乎必须在namespace std中或嵌套在namespace std中的类中,并且应该为ADL选择。 但不要这样做!: - )