首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么全局merge()函数与std::merge()冲突?

为什么全局merge()函数与std::merge()冲突?
EN

Stack Overflow用户
提问于 2013-10-28 22:43:05
回答 2查看 242关注 0票数 5

考虑以下代码:

代码语言:javascript
复制
#include <vector>
#include <algorithm>

template <typename Input1, typename Input2, typename Output>
void merge(Input1 begin1, Input1 end1, Input2 begin2, Input2 end2, Output out)
{
}

int main()
{
    std::vector<int> a = {1, 2};
    int b[] = {3, 4};
    int c[4];

    merge(a.begin(), a.end(), b, b + 2, c);
}

汇编收益:

代码语言:javascript
复制
$ clang++ -std=c++11 -stdlib=libc++ merge.cpp 
merge.cpp:15:5: error: call to 'merge' is ambiguous
    merge(a.begin(), a.end(), b, b + 2, c);
    ^~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/algorithm:4056:1: note: 
      candidate function [with _InputIterator1 = std::__1::__wrap_iter<int *>,
      _InputIterator2 = int *, _OutputIterator = int *]
merge(_InputIterator1 __first1, _InputIterator1 __last1,
^
merge.cpp:5:6: note: candidate function [with Input1 = std::__1::__wrap_iter<int
      *>, Input2 = int *, Output = int *]
void merge(Input1 begin1, Input1 end1, Input2 begin2, Input2 end2, Output out)
     ^
1 error generated.

编译器版本:

代码语言:javascript
复制
$ clang++ --version
Apple LLVM version 5.0 (clang-500.2.78) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

为什么对merge的调用模棱两可?它不确定我是指::merge()还是std::merge(),虽然很清楚(?)应该是::merge(),因为我没有指定任何using指令。我的merge函数位于全局命名空间中,我认为它不会与std名称空间中的任何内容发生冲突(因为这是名称空间的要点,对吗?)如果我将a更改为与其他数组一样的int数组,则它编译时没有任何歧义。另外,添加冒号并调用::merge()也很好。

所以我的问题是:这是Clang中的一个bug,还是我对名称空间有误解?为什么我对merge()的调用会导致歧义,因为这两个函数不在同一个名称空间中,并且没有使用任何using指令使std::merge()可见?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-28 22:49:39

问题是,std::vector<T>::iterator可能是类类型(在您的例子中,它是类类型):在重载解析过程中,编译器会查找函数的所有可见声明。为此,它将查找可能与其参数相关联的名称空间(这称为参数依赖查找)。类型std::vector<T>::iterator是在名称空间std (或嵌套在名称空间内的名称空间)中定义的,因此,重载解析考虑来自名称空间std的函数。由于std::merge()和您的merge()都匹配得很好,所以存在一个歧义。

避免此问题的最简单方法是为函数模板使用不同的名称。隐藏关联的命名空间是可能的,但并不容易:关联的命名空间是从定义类或类模板的位置以及它的基类和模板参数中提取的。因此,为任何迭代器类型创建包装模板是不够的,因为它仍然将原始命名空间与类型关联起来。您可能会尝试使您的函数模板更好地匹配,但考虑到它与标准算法一样通用,这也不太可行。

票数 5
EN

Stack Overflow用户

发布于 2013-10-28 22:52:51

这是由于来自std命名空间的迭代器的参数依赖查找(std)。

您可以编写::merge来获取函数,但我宁愿使用不同的名称。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19646434

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档