You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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(参数相关查找)被找到,请问:

  1. __gnu_cxx::copy_n是如何被找到的?
  2. 为何该代码在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 21:17:27