ADL 并不直接应用于template-id的诸如get<0>
,因此编译器并没有真正开始沿着这条路走下去。C++11 §14.8.1/8(在 C++03 中,14.8.1/6):
[注意:对于简单的函数名称,即使函数名称在调用范围内不可见,参数相关查找(3.4.2)也适用。这是因为调用仍然具有函数调用 (3.4.1) 的语法形式。但是,当使用具有显式模板参数的函数模板时,调用不具有正确的语法形式,除非在调用点存在具有该名称的函数模板可见。如果没有这样的名称可见,则该调用在语法上不是格式正确的,并且不适用依赖于参数的查找。如果某些此类名称可见,则应用依赖于参数的查找,并且可以在其他名称空间中找到其他函数模板。
它继续给出一个简短的例子。所以解决方法很简单:
#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!