为何GCC 9中`copy_n`调用存在二义性,GCC 13却无此问题?
问题描述
给出以下C++代码:
#include <ext/algorithm> #include <algorithm> #include <vector> int main() { std::vector<unsigned int> a[3], b[3]; copy_n(a, 3u, b); }
在g++-9中编译时出现重载歧义错误,错误信息如下:
a.cpp: In function ‘int main()’: a.cpp:8:20: error: call of overloaded ‘copy_n(std::vector<unsigned int> [3], unsigned int, std::vector<unsigned int> [3])’ is ambiguous 8 | copy_n(a, 3u, b); | ^ In file included from /usr/include/c++/9/algorithm:62, from /usr/include/x86_64-linux-gnu/c++/9/bits/stdc++.h:65, from a.cpp:1: /usr/include/c++/9/bits/stl_algo.h:799:5: note: candidate: ‘_OIter std::copy_n(_IIter, _Size, _OIter) [with _IIter = std::vector<unsigned int>*; _Size = unsigned int; _OIter = std::vector<unsigned int>*]’ 799 | copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) | ^~~~~~ In file included from /usr/include/c++/9/ext/ropeimpl.h:47, from /usr/include/c++/9/ext/rope:2975, from a.cpp:2: /usr/include/c++/9/ext/algorithm:120:5: note: candidate: ‘std::pair<_InputIterator, _ForwardIterator> __gnu_cxx::copy_n(_InputIterator, _Size, _OutputIterator) [with _InputIterator = std::vector<unsigned int>*; _Size = unsigned int; _OutputIterator = std::vector<unsigned int>*]’ 120 | copy_n(_InputIterator __first, _Size __count, _OutputIterator __result) | ^~~~~~
已知std::copy_n通过ADL(参数相关查找)被找到,请问:
__gnu_cxx::copy_n是如何被找到的?- 为何该代码在g++-13中可以正常编译?
解答
1. __gnu_cxx::copy_n 的查找逻辑
你包含了 <ext/algorithm> 头文件,该头文件在 __gnu_cxx 命名空间中定义了 copy_n 模板函数。在g++9中,编译器处理非限定名称的模板函数调用时,会将所有可见的同名称模板函数(无论所属命名空间)纳入重载决议的候选范围,因此 __gnu_cxx::copy_n 被找到并参与匹配。
而 std::copy_n 则是通过ADL机制找到的:函数参数是指向 std::vector 的指针,ADL会自动查找参数类型所属的 std 命名空间,从而找到 std::copy_n。
2. g++-13 可正常编译的原因
g++-13 对应的 libstdc++ 库对 <ext/algorithm> 中的 __gnu_cxx::copy_n 做了针对性调整:
- 要么直接移除了这个扩展版本的函数(因为C++标准已经提供了功能完备的
std::copy_n,扩展版本不再有存在的必要); - 要么为
__gnu_cxx::copy_n添加了模板约束,使其仅对非指针类型的迭代器生效,不再匹配代码中的指针参数。
这样一来,重载决议时只有 std::copy_n 是可行的候选函数,不会产生歧义,代码就能正常通过编译。
内容的提问来源于stack exchange,提问作者ruixiao liu
相关产品推荐
相关产品推荐

