假设我有一个类扩展了一个(STL)容器并提供了一个惯用的 begin
成员函数:
#include <vector>
template <typename Cont>
struct Bar {
Cont c;
auto my_begin() { return begin(c); }
};
int main() {
Bar<std::vector<int>> b;
b.my_begin();
}
通过 ADL,我不必指定 std::
在 begin()
之前称呼。这很好,因为 std::begin(v)
总是会尝试调用v.begin()
,用户可能想要使用没有 .begin()
的自定义容器接口(interface),所以如果他定义了自己的自由函数begin(v)
, Bar
会使用它。但是,如果我重命名
my_begin
,ADL 似乎将不再起作用至begin
也好似被蒙上了一层阴影。编译器只会提示它在类范围内找不到匹配的调用:prog.cc: In instantiation of 'auto Bar<Cont>::begin() [with Cont = std::vector<int>]':
prog.cc:11:13: required from here
prog.cc:6:27: error: use of 'auto Bar<Cont>::begin() [with Cont = std::vector<int>]' before deduction of 'auto'
6 | auto begin() { return begin(c); }
| ^~~~~
prog.cc:6:32: error: no matching function for call to 'Bar<std::vector<int> >::begin(std::vector<int>&)'
6 | auto begin() { return begin(c); }
| ~~~~~^~~
prog.cc:6:10: note: candidate: 'auto Bar<Cont>::begin() [with Cont = std::vector<int>]'
6 | auto begin() { return begin(c); }
| ^~~~~
prog.cc:6:10: note: candidate expects 0 arguments, 1 provided
当然,写 std::begin
,代码将再次运行,但这只会显示 ADL 的排除。除了重命名成员函数,我还能做什么?
最佳答案
您可以只使用两步方法:
auto begin() {
using std::begin; //1
return begin(c); //2
}
1
: 带std::begin
考虑到2
: 如果 c
有 begin()
在其命名空间中,调用它,否则默认为 std::begin()
您可以阅读更多信息 here
关于c++ - 在 ADL 期间如何防止遮盖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63337303/