1

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.

user17732522
  • 53,019
  • 2
  • 56
  • 105
glades
  • 3,778
  • 1
  • 12
  • 34

1 Answers1

1

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:

using std::begin;
auto it = begin(hello);

This will always find std::begin, but also do ADL to find other begin overloads.

You can also use a qualified call std::begin(hello); which will forward correctly to the .begin member 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 correct begin for the argument more generally, either to a member if possible or via ADL.

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • Ty, but this way I always have to write `using std::begin` into every method that uses std::begin()? That also seems tedious.. – glades Feb 21 '22 at 17:47
  • @glades You probably just want `std::begin(hello);` or `std::ranges::begin(hello);` and not bother with ADL at all. Discussion on whether or not to use `using std::begin;` followed by unqualified call [here](https://stackoverflow.com/questions/31604984/is-using-stdbegin-a-good-practice/31607065). – user17732522 Feb 21 '22 at 17:58