如何防止 ADL 期间出现阴影?

Jod*_*cus 3 c++ templates argument-dependent-lookup

假设我有一个扩展(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();
}
Run Code Online (Sandbox Code Playgroud)

通过ADL,我不必std::begin()调用前指定。这很好,因为std::begin(v)总是尝试调用v.begin(),用户可能想要使用没有.begin()接口的自定义容器,因此如果他定义了自己的自由函数begin(v)Bar就会使用它。但是,如果我也重命名my_begin为ADL,似乎 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
Run Code Online (Sandbox Code Playgroud)

当然,通过编写std::begin,代码将再次运行,但这只是体现了 ADL 的排除。除了重命名成员函数,我还能做什么?

Waq*_*med 6

您可以只使用两步法:

    auto begin() { 
        using std::begin;   //1
        return begin(c);    //2
    }
Run Code Online (Sandbox Code Playgroud)

1:把std::begin考虑
2:如果cbegin()在其命名空间,调用,否则默认为std::begin()

你可以在这里阅读更多关于它的信息