作者:刘海龙_高安大城 | 来源:互联网 | 2023-01-26 18:26
我正在尝试编写一个模板函数,该函数使用已解析的ADL get
来获取struct/range(tuple
-esque)的成员.
#include
#include
#include
int main() {
auto tup = std::make_tuple(1, 2);
std::cout <(tup) <
我这样做是因为结构化绑定提案(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf§11.5.3 )说的是如何get
习惯的从结构中获取元素.它表示非成员get
用于从结构中获取元素.
我假设上面的代码会编译,因为ADL会导致get
在std
命名空间中查找函数(因为它的参数是类型std::tuple
,在其中std
),在那里可以找到它.但是,我收到了一个错误.有人可以在这里解释正确的方法,以及为什么上面的代码不起作用?在这种情况下如何强制ADL发生?
1> Barry..:
问题最终是模板:
std::cout <(tup) <
此时,编译器不知道这是一个需要使用ADL查找的函数 - get
只是一个名称.因为这个名字本身没有找到任何东西,所以这将被解释为一个未知的名称,后跟小于.要使其工作,您需要一些其他功能模板get
可见:
using std::get;
std::cout <(tup) <
即使它什么都不做:
template void get();
int main() {
auto tup = std::make_tuple(1, 2);
std::cout <(tup) <
结构化绑定措辞get
使用依赖于参数的查找显式查找,因此它不需要get
从[dcl.struct.bind] 获得已命名的已命名函数模板:
在不合格-ID get
在范围查找E
由类成员访问查询,以及如果找到至少一个声明,初始化为e.get()
.否则,初始化器get(e)
,其中get
在相关的命名空间抬头.在任何一种情况下,都get
被解释为模板ID.[注意:不执行普通的非限定查找. - 结束说明]
说明是关键.如果我们执行了不合格的查找,我们就会失败.
2> Justin..:
对于给出显式模板参数的函数模板, Argument Dependent Lookup的工作方式不同.
虽然函数调用可以通过ADL解析,即使普通查找没有找到任何内容,但是对具有显式指定模板参数的函数模板的函数调用要求通过普通查找找到模板的声明(否则,它是语法错误遇到一个未知的名字后跟一个小于号的字符)
基本上,需要有一些方法可以使非限定查找找到模板函数.然后,ADL可以启动(因为该名称get
已知为模板).Cppreference给出了一个例子:
namespace N1 {
struct S {};
template void f(S);
}
namespace N2 {
template 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循环执行非成员函数的查找开始和结束
从模板实例化的角度查找从属名称.
非成员函数的查找由类似元组的类型的结构化绑定声明执行
强调补充说