以下代码不是在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 ,我想知道这是否是一个“功能”。这背后的理由是什么?除此之外,全局命名空间还会受到更多污染吗?
-stdlib=libc++
-stdlib=libstdc++
/std:c++20
std::get 是通过参数相关查找(ADL)找到的,因为 t 具有类模板的专用类型 std::tuple 其位于与 std::获取 要使用的过载。这是C++中一直存在的行为,也是使运算符重载以及其他可自定义函数调用(如 swap 。
std::get
t
std::tuple
std::获取
swap
它在C++17中失败的原因与是否 std::获取 是找到的,而是使用确定 < 下列的 get 是小于运算符或模板参数列表的开头。在C++20之前,如果在 < 通过通常的不合格(非ADL)查找根本找不到,程序格式不正确。由于C++20,因此假定在这种情况下引入一个模板参数列表。
<
get
例如,如果添加名为的函数模板 收到 ,不考虑签名,例如。
收到
template<typename T> void get();
进入全局命名空间范围,然后 < 还将被假定引入模板参数列表,因为此函数模板是为 收到 通过通常的不合格查找,即使在C++17中也是如此。然后ADL像往常一样应用于调用(在每个C++版本中都是这样) std::获取 也将作为候选人。