Arm*_*yan 7 c++ iterator stl std argument-dependent-lookup
我无意在实际代码中使用它.我承诺.
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?
}
Run Code Online (Sandbox Code Playgroud)
换句话说,迭代器类是否可以在stdADL不考虑的命名空间中定义?
提前致谢.
::iterator标准容器的确切类型等是实现定义的,因此理论上没有什么能阻止它成为typedef外部的东西std::(例如普通指针).
我在标准中找不到其他任何暗示ADL将始终在这种情况下工作的东西,所以 - 除非有人纠正我 - 我将不得不说答案是:不,你不能假设这find将通过ADL找到.
我相信在最一般的情况下答案是否定的,但对于大多数实际实施来说是肯定的.
根据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选择. 但是不要这样做!:-)