以下代码不能在 C++17 中编译,但可以在 C++20 中编译:
#include <tuple>
int main() {
auto t = std::make_tuple(1, 2);
get<0>(t); // no std:: required!
return 0;
}
由于这适用于 g++ 和 clang++ 以及
-stdlib=libc++
和 -stdlib=libstdc++
,甚至在 msvc 中也适用于 /std:c++20
,我想知道这是否是一个“功能”。这背后的理由是什么?除此之外还有对全局命名空间的更多污染吗?
std::get
是通过与参数相关的查找找到的,因为 t
具有类型 std::tuple
,它与您要使用的 std::get
重载位于同一命名空间范围内。
在 C++17 中失败的原因与是否找到
std::get
无关,而是与确定 <
后面的 get
是否为小于运算符或开始的规则有关。模板参数列表。在 C++20 之前,如果通过通常的非限定(非 ADL)查找根本找不到 <
之前的非限定名称,则程序格式错误。从 C++20 开始,假定在这种情况下引入模板参数列表。
例如,如果您添加模板
template<typename T>
void get();
进入全局命名空间范围,那么
<
也将被假定引入模板参数列表,因为这个函数模板是通过通常的非限定查找找到 get
的,即使在 C++17 中也是如此。