7

我无意在实际代码中使用它。我保证。

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?
}

换句话说,迭代器类是否可以定义在stdADL 不会考虑的命名空间中?

提前致谢。

4

2 回答 2

5

::iterator标准容器的 etc. 的确切类型是implementation-defined,所以理论上没有什么可以阻止它成为typedef外部的东西std::(例如普通指针)。

我在标准中找不到任何其他内容表明 ADL 在这种情况下始终有效,所以——除非有人纠正我——我不得不说答案是:不,你不能假设这find将通过 ADL 找到。

于 2011-07-23T22:09:09.377 回答
5

我相信在最一般的情况下答案是否定的,但对于大多数实际的实现来说是肯定的。

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

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

这表明如果迭代器类型确实是某个容器(如 )内的嵌套类型std::set,那么调用中该迭代器的关联命名空间find将是std,因为std::set它是一个关联类并且std是包含set. 然后标准说(§3.4.2/2a)

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

这意味着您确实会findnamespace std.

但是,这不能保证通常有效。我们还从规范(§3.4.2)中得到

用于指定类型的 Typedef 名称和 using-declarations 不构成该集合。

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

于 2011-07-23T22:11:02.350 回答