作为一项学习练习,我一直reimplementing some of the STL algorithm。即使我没有添加任何using指令或使用std命名空间my test code won't compile unless I explicitly prefix those functions shadowing std names的声明。
我认为这是因为当我将std :: vector迭代器作为参数传递给我的函数时,参数依赖查找从std命名空间引入函数。
一个小程序来说明我的问题:
#include <vector>
#include <algorithm>
namespace danstd {
template <typename I, typename T>
I find(I b, I e, T val) {
for (; b != e; ++b) {
if (*b == val)
return b;
}
return e;
}
}
using namespace danstd;
int main() {
std::vector<int> v = {1, 2, 3};
auto i = find(begin(v), end(v), 3);
return i == end(v) ? -1 : *i;
}
编译时,我看到以下错误消息:
$ g++ -Wall foo.cpp
foo.cpp: In function ‘int main()’:
foo.cpp:16:37: error: call of overloaded ‘find(std::vector<int>::iterator, std::vector<int>::iterator, int)’ is ambiguous
return *find(begin(v), end(v), 3);
^
foo.cpp:5:3: note: candidate: I find(I, I, T) [with I = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; T = int]
I find(I b, I e, T val) {
^~~~
In file included from /usr/include/c++/6/algorithm:62:0,
from foo.cpp:2:
/usr/include/c++/6/bits/stl_algo.h:3784:5: note: candidate: _IIter std::find(_IIter, _IIter, const _Tp&)[with _IIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Tp = int]
find(_InputIterator __first, _InputIterator __last,
^~~~
在单元测试代码中,我已经链接到上面,我已经将我的函数包装在danstd命名空间中,并且我在表单danstd::function(...)
上进行了每次调用。是否有任何方法可以使用完全限定名称来避免与std名称的命名冲突?
答案 0 :(得分:3)
我认为这是因为当我将std :: vector迭代器作为参数传递给我的函数时,参数依赖查找从std命名空间引入函数。
这是正确的。由于std::vector::iterator
位于std
,因此会在std
中进行查找。
有没有办法使用完全限定名称来避免与std名称的命名冲突?
不幸的是没有。您需要符合要求来自全球空间的
return *::find(begin(v), end(v), 3);
答案 1 :(得分:2)
您可以按照以下方式消除呼叫歧义
return *::find(begin(v), end(v), 3);
如果没有这个,编译器是正确的,因为你已经注意到由于参数依赖的查找而导致调用不明确
答案 2 :(得分:1)
C ++旨在将函数与给定命名空间中的类型相关联。只要名称空间用于封装库,这是一个有效的假设。
算法库的类型在另一个已定义相同算法的库的命名空间中定义。一种解决方案是实现自己的类型......即使是一个标准容器也是一种练习;)。
答案 3 :(得分:1)
我在表格
danstd::function(...)
上进行每次通话。
不,你不是。你有using namespace danstd
语句将你的find()
函数转储到全局命名空间,然后你调用它而不限定它。
因此,要么从全局命名空间中限定它:
namespace danstd {
...
template <typename I, typename T>
I find(I b, I e, const T &val) { ... }
}
using namespace danstd;
auto i = ::find(begin(v), end(v), 3);
或者删除using
语句并使用命名空间完全限定函数调用:
namespace danstd {
...
template <typename I, typename T>
I find(I b, I e, const T &val) { ... }
}
// using namespace danstd;
auto i = danstd::find(begin(v), end(v), 3);