c++ 非限定查找期间的参数相关查找首选项

wj8zmpe1  于 2023-05-02  发布在  其他
关注(0)|答案(1)|浏览(92)

我正在尝试理解基于ADL的查找。以下代码段由于不明确的重载而导致编译错误(下面的错误)。ADL找到的版本不应该优先选择吗?

template <typename It, typename F>
void for_each(It begin, It end, F f) {}

int main() {
    std::vector<int> vec;
    for_each(vec.begin(), vec.end(), [](int &x){});  
}
source>: In function 'int main()':
<source>:70:13: error: call of overloaded 'for_each(std::vector<int>::iterator, std::vector<int>::iterator, main()::<lambda(int&)>)' is ambiguous
   70 |     for_each(vec.begin(), vec.end(), [](int &x){});
      |     ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:64:6: note: candidate: 'void for_each(It, It, F) [with It = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; F = main()::<lambda(int&)>]'
   64 | void for_each(It begin, It end, F f) {
      |      ^~~~~~~~
In file included from /opt/compiler-explorer/gcc-trunk-20230422/include/c++/14.0.0/algorithm:61,
                 from <source>:3:
/opt/compiler-explorer/gcc-trunk-20230422/include/c++/14.0.0/bits/stl_algo.h:3827:5: note: candidate: '_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<int*, vector<int> >; _Funct = main()::<lambda(int&)>]'
 3827 |     for_each(_InputIterator __first, _InputIterator __last, _Function __f)
hujrc8aj

hujrc8aj1#

ADL找到的版本不应该优先选择吗?
这不是ADL的功能。检查相关名称空间的目的是找到否则无法找到的 * 候选项 *(但可以说是名称空间中类型的API的自然组成部分)。
这些候选者不是首选的,而是与常规查找规则找到的任何候选者沿着进入过载解决过程,在这里我们可能会有冲突。由于我们比较的for_each的两个重载都是从模板生成的,可行的,无约束的,并且在函数模板的偏序中没有比彼此更高的排名,因此调用是不明确的。
在看这样一个简单的例子时,这似乎是违反直觉的,但是停止编译并让程序员解决冲突确实是唯一安全的选择。C++是非常复杂的,在名称可以被带入范围的各种方式之间,并且在ADL期间可以检查多个相关的名称空间,如果语言在调用周围的代码以某种不可见的方式改变时选择另一个重载,那就不好了。

相关问题