如何解决“ std :: transform”编译时没有在多个编译器上进行限定名称查找?
当我发现对std::transform
的调用意外编译良好而没有使用std::
名称空间前缀完全限定调用时,我正在用C ++写一个库。根据C ++文档,std::transform
是在std::
命名空间中定义的,因此在不完全限定名称的情况下不应进行编译。
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v{ 1,2,3 };
// "transform" is supposed to be in the namespace "std::"???
transform(v.begin(),v.end(),v.begin(),[](const auto& value) {
return value + 1;
});
}
起初,我认为这是自从我在Visual Studio中工作以来在标准库的Microsoft实现中的一个错误,但是后来我在https://godbolt.org/上用了许多不同的编译器对其进行了测试,并且似乎可以编译在其他编译器上也没有错误!
将transform
调用更改为::transform
会导致编译失败,因此很明显在全局名称空间中没有transform
的符号。
我的猜测是,在<algorithm>
头文件中的某个地方,有人意外地在全局命名空间中键入了using std::transform;
,这将使得该函数可以在没有std::
前缀的情况下被调用...但是会被认为是不好的做法,并且会是标准库实现中的错误吗?
我只是在 多个 编译器的标准库实现中发现了一个错误!如果是这样,我什至会报告这个错误?
解决方法
不,这不是bug 1 。这是argument dependent lookup(又名Koenig查找)。
当函数的参数位于特定的命名空间中时,编译器将在该命名空间中查找函数本身。
在这种情况下,关系可能不明显,但是函数的参数是v.begin()
返回的值,类似于std::vector<int>::iterator
2 ,因此编译器也在功能的名称空间std
中查找。
1.然而,这是一种非常出乎意料的行为,一些人不仅会而且还认为这是语言定义中的错误。
2.但这可能并不是它的确切名称。向量具有相同的迭代器类型(即使它们具有不同的分配器类型)也很有用,并且这样做通常会在向量之外定义迭代器类型。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。