I am trying to code a template function that uses an ADL resolved get
to fetch members of a struct/range (tuple
-esque).
#include <iostream>
#include <utility>
#include <tuple>
int main() {
auto tup = std::make_tuple(1, 2);
std::cout << get<0>(tup) << std::endl;
}
I am doing this because of what the structured bindings proposal (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf §11.5.3) says about how get
is used to fetch elements from the struct. It says that a non member get
is used to fetch elements from within the struct.
I assumed that the code above would compile, because ADL would cause the get
function to be looked for in the std
namespace (because it's argument is of type std::tuple<int, int>
, which is in std
), where it would be found. But, I get an error. Can someone explain the right approach here and also why the code above does not work? How can one force ADL to happen in this case?
The problem ultimately is templates:
std::cout << get<0>(tup) << std::endl;
// ~~~~
At that point, the compiler doesn't know that this is a function that needs to be looked up using ADL yet - get
is just a name. And since that name by itself doesn't find anything, this is going to be interpreted as an unknown name followed by less-than. To get this to work, you need some other function template get
visible:
using std::get;
std::cout << get<0>(tup) << std::endl; // now, OK
Even if it does nothing:
template <class T> void get();
int main() {
auto tup = std::make_tuple(1, 2);
std::cout << get<0>(tup) << std::endl;
}
The structured binding wording explicitly looks up get
using argument-dependent lookup, so it avoids the need to have an already-visible function template named get
, from [dcl.struct.bind]:
The unqualified-id
get
is looked up in the scope ofE
by class member access lookup, and if that finds at least one declaration, the initializer ise.get<i>()
. Otherwise, the initializer isget<i>(e)
, whereget
is looked up in the associated namespaces. In either case,get<i>
is interpreted as a template-id. [ Note: Ordinary unqualified lookup is not performed. — end note ]
The note is the key. If we had performed unqualified lookup, we'd just fail.