c++ - “std::transform”在多个编译器上编译时没有限定名称查找?
问题描述
我正在用 C++ 编写一个库,当时我发现调用std::transform
意外地编译得很好,而没有完全限定具有std::
命名空间前缀的调用。根据 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;
});
}
起初我认为这是标准库的 Microsoft 实现中的一个错误,因为我在 Visual Studio 中工作,但后来我在https://godbolt.org/上使用一堆不同的编译器对其进行了测试,它似乎可以编译在其他编译器上也没有错误!
更改transform
调用会::transform
导致编译失败,因此很明显全局命名空间中没有符号 for transform
。
我的猜测是,在<algorithm>
头文件的某个地方,有人不小心输入using std::transform;
了全局命名空间,这将使函数可以在没有std::
前缀的情况下调用......但这将被认为是不好的做法,并且会成为标准库实现中的错误不会它?
我是否只是在多个编译器的标准库实现中发现了一个错误!?如果是这样,我什至会如何报告这样的错误?
解决方案
不,这不是错误1 。这是依赖于参数的查找(又名 Koenig 查找)。
当函数的参数位于特定命名空间中时,编译器将在该命名空间中查找函数本身。
在这种情况下,这种关系可能并不明显,但函数的参数是v.begin()
返回值,类似于std::vector<int>::iterator
2,因此编译器std
也会在命名空间中查找函数。
1. 然而,这是一种足够出乎意料的行为,有些人不仅会,而且认为这是语言定义中的一个错误。
2. 但这可能不是它的确切名称。向量具有相同的迭代器类型很有用,即使它们具有不同的分配器类型,并且要做到这一点,迭代器类型通常会在向量之外定义。
推荐阅读
- reactjs - The operation was rejected by your operating system
- python - Variables in Python MySQL connector not working when in function
- django - Django multiple Project using same database tables
- php - how to make authentic user afte login cant going to admin page
- aws-cdk - CDK Stepfunction Fargate step that takes all json key
- php - 我在使用 PHP sha256 Hash 时遇到了一些问题
- php - 如何使用打开/关闭原则替换修改共享状态的开关块
- vim - Unable to get out of terminal window inside VIM using VIM key bindings
- jquery - Radio input section toggle with jQuery
- sql - SUM FIRST_VALUE 或 SUM group by 同时仍显示所有行?