According to cppreference, in Argument-dependent lookups
function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.
However, why is it then that in the following example in function A::member_function() the class-method begin() is choosen which 1) takes 0 arguments and 2) isn't even in the namespace of std::vector, the argument of the function? Shouldn't ADL go to the namespace of the arguments (which is std for vector) and choose the free function std::begin()?
#include <unordered_map>
#include <vector>
class A
{
public:
using value_t = std::unordered_map<int, char>;
public:
void member_function();
value_t::iterator begin() { return map_.begin(); }
private:
value_t map_;
};
void A::member_function()
{
std::vector<int> hello;
auto it = begin(hello);
}
I'm also happy for a workaround if this is really the way ADL works.
ADL is not done if ordinary unqualified name lookup finds a class member.
You can avoid this issue with a using-declaration, so that unqualified name lookup is guaranteed to always result in
std::begin:This will always find
std::begin, but also do ADL to find otherbeginoverloads.You can also use a qualified call
std::begin(hello);which will forward correctly to the.beginmember of the argument, if possible, but will not do any ADL.In C++20 there is
std::ranges::begin, which can be used instead of the method above. It is a customization point object and will forward to the correctbeginfor the argument more generally, either to a member if possible or via ADL.