为什么 ADL 不能使用 std::get 解析为正确的函数
Why ADL does not resolve to the correct function with std::get
我正在尝试编写一个模板函数,该函数使用 ADL 解析get
来获取结构/范围的成员(tuple
-esque
#include <iostream>
#include <utility>
#include <tuple>
int main() {
auto tup = std::make_tuple(1, 2);
std::cout << get<0>(tup) << std::endl;
}
我这样做是因为结构化绑定提案 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf§11.5.3( 关于如何使用get
从结构中获取元素的内容。 它说非成员get
用于从结构中获取元素。
我假设上面的代码会编译,因为 ADL 会导致在std
命名空间中查找get
函数(因为它的参数是std::tuple<int, int>
类型,在std
中(,在那里可以找到它。 但是,我收到一个错误。 有人可以在这里解释正确的方法以及为什么上面的代码不起作用吗? 在这种情况下,如何强制ADL发生?
问题最终是模板:
std::cout << get<0>(tup) << std::endl;
// ~~~~
此时,编译器还不知道这是一个需要使用 ADL 查找的函数 -get
只是一个名称。由于该名称本身找不到任何内容,因此这将被解释为一个未知名称,后跟小于。要使其正常工作,您需要一些其他get
可见的函数模板:
using std::get;
std::cout << get<0>(tup) << std::endl; // now, OK
即使它什么都不做:
template <class T> void get();
int main() {
auto tup = std::make_tuple(1, 2);
std::cout << get<0>(tup) << std::endl;
}
结构化绑定措辞使用依赖于参数的查找显式查找get
,因此它避免了需要具有名为get
的已经可见的函数模板,来自 [dcl.struct.bind]:
非限定 id
get
在类成员访问查找的E
范围内查找,如果找到至少一个声明,则初始值设定项e.get<i>()
。否则,初始值设定项为get<i>(e)
,其中get
在关联的命名空间中查找。在任一情况下,get<i>
都被解释为模板 ID。[ 注:不执行普通非限定查找。
笔记是关键。如果我们执行了不合格的查找,我们就会失败。
参数相关查找对于给定显式模板参数的函数模板的工作方式不同。
尽管函数调用可以通过 ADL 解决,即使普通 查找什么也没找到,函数调用函数模板 显式指定的模板参数要求存在 通过普通查找找到的模板的声明(否则为 遇到未知名称后跟小于的语法错误 字符(
基本上,非限定查找需要某种方法来查找模板函数。然后,ADL 可以启动(因为名称get
然后已知是模板(。Cpp首选项举了一个例子:
namespace N1 { struct S {}; template<int X> void f(S); } namespace N2 { template<class T> void f(T t); } void g(N1::S s) { f<3>(s); // Syntax error (unqualified lookup finds no f) N1::f<3>(s); // OK, qualified lookup finds the template 'f' N2::f<3>(s); // Error: N2::f does not take a non-type parameter // N1::f is not looked up because ADL only works // with unqualified names using N2::f; f<3>(s); // OK: Unqualified lookup now finds N2::f // then ADL kicks in because this name is unqualified // and finds N1::f }
结构化绑定是一种特殊情况,启用了 ADL。
在以下上下文中,仅 ADL 查找(即在 仅关联的命名空间(发生:
- 如果成员查找失败,则由 range-for 循环执行的非成员函数的查找开始和结束
- 从模板实例化点开始的依赖名称查找。
- 非成员函数的查找通过类元组类型的结构化绑定声明执行
强调添加
快进到 C++20
被 C++20 接受的 p0846r0 现在允许 ADL 调用具有显式模板参数的模板函数。
因此,OP 的代码现在可以按原样编译 C++20 而不会出现错误!
- C++中是否有任何函数等同于python中字典的get函数?
- 如何将 c++ get 函数代码转换为 opencv 算法中使用的 python
- 使用"push_back"作为带有"get"函数C++的向量
- 从 unique_ptr::get 发送指针作为指针引用进入函数
- c++ 在类中声明私有的向量,但有一个 get 函数
- c++为什么ifstream get()函数返回无法识别的特殊字符
- 使用Set/Get-like方法或GetSet组合函数
- 为什么 std::get<T> 其中 T 是调用 constexpr 函数失败的结果?
- 如何在输入成员函数中使用 get()
- C++ :: 设置值函数在函数内设置,但后跟 Get 函数,设置值消失了
- 为什么 ADL 不能使用 std::get 解析为正确的函数
- 在类中使用映射并通过其他类的 get() 和 set() 函数访问值
- C++11: 如何编写一个像 Get 一样工作的模板函数<tuple>...但是收到参数包?
- get 函数返回无效值
- cin.get()函数在C 中
- 通过引用将私有类实例传递到另一个类 C++ 的"get"函数中
- 类成员函数 get 不会返回值
- ifstream 函数"get"如何改变其字符参数?
- 重载运算符()与成员函数get()
- 输入流函数get在c++中