ADL doesn't directly apply to template-id's such as get<0>
, so the compiler doesn't really get started down that path. C++11 §14.8.1/8 (in C++03, 14.8.1/6):
[ Note: For simple function names, argument dependent lookup (3.4.2) applies even when the function name is not visible within the scope of the call. This is because the call still has the syntactic form of a function call (3.4.1). But when a function template with explicit template arguments is used, the call does not have the correct syntactic form unless there is a function template with that name visible at the point of the call. If no such name is visible, the call is not syntactically well-formed and argument-dependent lookup does not apply. If some such name is visible, argument dependent lookup applies and additional function templates may be found in other namespaces.
It goes on to give a short example. So the workaround is quite easy:
#include <tuple>
template< typename > // BEGIN STUPID BUT HARMLESS HACK
void get( struct not_used_for_anything ); // END STUPIDITY
auto t = std::make_tuple(false, false, true);
bool a = get<0>(t); // Now the compiler knows to use ADL!
bool b = std::get<0>(t); // okay
http://ideone.com/fb8Ai
Note that the not_used_for_anything
in the above is merely a safety mechanism. It's intended to be an incomplete type which is never completed. Omitting it works as well, but is unsafe because it could collide with a signature you might want.
template< typename >
void get() = delete;
http://ideone.com/WwF2y
Note: the above quote from the Standard is non-normative, meaning that in the opinion of the Committee, we would be able to figure this out without explanation, because it's implied by the rest of the language and grammar, particularly the fact that 3.4.2 says nothing about looking up template-ids. Yeah, right!