C++ 为什么ADL不能通过std::get解析为正确的函数

C++ 为什么ADL不能通过std::get解析为正确的函数,c++,tuples,c++17,structured-bindings,C++,Tuples,C++17,Structured Bindings,我试图编写一个模板函数,该函数使用ADL解析的get获取结构/范围(tuple-esque)的成员 #包括 #包括 #包括 int main(){ auto tup=std::make_tuple(1,2); std::cout依赖于参数的查找的工作方式不同 虽然函数调用可以通过ADL解决,即使是普通的 查找找不到任何内容,即对具有 显式指定的模板参数要求 声明通过普通查找找到的模板(否则为 遇到未知名称后跟小于的语法错误 (字符) 基本上,非限定查找需要某种方法来找到模板函数。然后,ADL可以

我试图编写一个模板函数,该函数使用ADL解析的
get
获取结构/范围(
tuple
-esque)的成员

#包括
#包括
#包括
int main(){
auto tup=std::make_tuple(1,2);

std::cout依赖于参数的查找的工作方式不同

虽然函数调用可以通过ADL解决,即使是普通的 查找找不到任何内容,即对具有 显式指定的模板参数要求 声明通过普通查找找到的模板(否则为 遇到未知名称后跟小于的语法错误 (字符)

基本上,非限定查找需要某种方法来找到模板函数。然后,ADL可以启动(因为名称
get
被称为模板)。Cppreference给出了一个示例:

名称空间N1{
结构S{};
模板空白f(S);
}
命名空间N2{
模板空隙f(T);
}
空g(N1::S){
f(s);//语法错误(非限定查找未找到f)
N1::f(s);//好的,限定查找将查找模板“f”
N2::f(s);//错误:N2::f不接受非类型参数
//N1::f未被查找,因为ADL仅起作用
//没有限定名称的
使用N2::f;
f(s);//确定:非限定查找现在找到N2::f
//然后ADL开始工作,因为这个名称是不合格的
//并找到N1::f
}
结构化绑定是一种特殊情况,启用了ADL

在以下上下文中,仅ADL查找(即在 仅关联名称空间)发生:

  • 如果成员查找失败,则非成员函数的查找由循环范围开始和结束
  • 从模板实例化点开始的依赖名称查找
  • 通过对类元组类型的结构化绑定声明执行非成员函数的查找

重点补充

问题最终在于模板:

std::cout << get<0>(tup) << std::endl;
//           ~~~~
即使它什么也不做:

template <class T> void get();

int main() {
    auto tup = std::make_tuple(1, 2); 
    std::cout << get<0>(tup) << std::endl;
}
template void get();
int main(){
auto tup=std::make_tuple(1,2);
std::cout快进到C++20
C++20现在允许ADL使用显式模板参数调用模板函数


所以OP的代码没有错误!

非常有趣!不过我想知道,引入这个未定义的函数是否会导致其他问题?比如冲突之类的问题?奇怪的是,如果它最终成为首选,它会是什么样子。我的意思是,实际上不要这样做-我只是出于解释的目的把它放在那里。嗯,我有没有办法强制DL会发生什么?我尝试了
模板
关键字,但当然不起作用。@question Out of structured bindings,No.另外,我发誓有一个语言建议可以让它起作用,但我找不到。@Barry,您记得的可能是Robert Haberlach的D0389R1,但它被替换为C++20中接受的D0389R1,现在说
std::cout@DanielH哪一个可行?如果有人提出,听起来可能可行。谢谢你的回答。我想接受两个答案,但因为另一个答案包含一个简单解析技术的简单示例。我将接受。请注意。
std::cout << get<0>(tup) << std::endl;
//           ~~~~
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;
}