代码之家  ›  专栏  ›  技术社区  ›  Mircode

在C++20中,<tuple>中的get<>()函数不再位于命名空间std中。为什么?[副本]

  •  2
  • Mircode  · 技术社区  · 2 年前

    以下代码不是在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 ,我想知道这是否是一个“功能”。这背后的理由是什么?除此之外,全局命名空间还会受到更多污染吗?

    1 回复  |  直到 2 年前
        1
  •  6
  •   user17732522    2 年前

    std::get 是通过参数相关查找(ADL)找到的,因为 t 具有类模板的专用类型 std::tuple 其位于与 std::获取 要使用的过载。这是C++中一直存在的行为,也是使运算符重载以及其他可自定义函数调用(如 swap

    它在C++17中失败的原因与是否 std::获取 是找到的,而是使用确定 < 下列的 get 是小于运算符或模板参数列表的开头。在C++20之前,如果在 < 通过通常的不合格(非ADL)查找根本找不到,程序格式不正确。由于C++20,因此假定在这种情况下引入一个模板参数列表。

    例如,如果添加名为的函数模板 收到 ,不考虑签名,例如。

    template<typename T>
    void get();
    

    进入全局命名空间范围,然后 < 还将被假定引入模板参数列表,因为此函数模板是为 收到 通过通常的不合格查找,即使在C++17中也是如此。然后ADL像往常一样应用于调用(在每个C++版本中都是这样) std::获取 也将作为候选人。